From 0b28b8d3ab9c0038b7f9f45f10050ccb8dc57896 Mon Sep 17 00:00:00 2001 From: DiMartinoXBMC Date: Sat, 13 Feb 2016 20:33:16 +0300 Subject: [PATCH] new settings --- .idea/workspace.xml | 1955 ++++++++++++------------ AceStream.py | 2 +- Anteoloader.py | 15 +- Content.py | 2 +- Core.py | 12 +- Downloader.py | 2 +- Libtorrent.py | 10 +- Localization.py | 2 +- Player.py | 17 +- SearcherABC.py | 2 +- addon.xml | 2 +- changelog.txt | 6 +- controlcenter.py | 2 +- default.py | 2 +- functions.py | 99 +- resources/language/English/strings.xml | 9 +- resources/language/Russian/strings.xml | 6 +- resources/settings.xml | 35 +- 18 files changed, 1136 insertions(+), 1044 deletions(-) diff --git a/.idea/workspace.xml b/.idea/workspace.xml index 86aeb4a..b6d2e61 100644 --- a/.idea/workspace.xml +++ b/.idea/workspace.xml @@ -1,9 +1,25 @@ - + + + + + + + + + + + + + + + + + @@ -36,139 +52,243 @@ - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -177,132 +297,16 @@ - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - - - - - - - - - - - - @@ -310,91 +314,30 @@ - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + @@ -404,7 +347,97 @@ - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -432,26 +465,6 @@ @@ -517,7 +550,6 @@ - @@ -536,22 +568,9 @@ - - - - - - - - + @@ -572,6 +591,116 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + + - + @@ -1052,7 +1182,6 @@ - @@ -1069,10 +1198,6 @@ - - - - @@ -1094,141 +1219,19 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -1313,13 +1316,6 @@ - - - - - - - @@ -1341,88 +1337,6 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -1430,21 +1344,6 @@ - - - - - - - - - - - - - - - @@ -1452,360 +1351,502 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + + - + - + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + - - + + - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + - + - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - \ No newline at end of file diff --git a/AceStream.py b/AceStream.py index b2f302b..699d7e9 100644 --- a/AceStream.py +++ b/AceStream.py @@ -2,7 +2,7 @@ ''' Torrenter v2 plugin for XBMC/Kodi Copyright (C) 2012-2015 Vadim Skorba v1 - DiMartino v2 - http://forum.kodi.tv/showthread.php?tid=214366 + https://forums.tvaddons.ag/addon-releases/29224-torrenter-v2.html This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/Anteoloader.py b/Anteoloader.py index 62ffa62..8eca8ec 100644 --- a/Anteoloader.py +++ b/Anteoloader.py @@ -2,6 +2,7 @@ ''' Torrenter v2 plugin for XBMC/Kodi Copyright (C) 2012-2015 Vadim Skorba v1 - DiMartino v2 + https://forums.tvaddons.ag/addon-releases/29224-torrenter-v2.html This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -37,7 +38,7 @@ import sys from contextlib import contextmanager, closing, nested -from functions import calculate, showMessage, clearStorage, WatchedHistoryDB, get_ids_video, log, debug +from functions import calculate, showMessage, clearStorage, WatchedHistoryDB, get_ids_video, log, debug, ensure_str from torrent2http import State, Engine, MediaType @@ -175,7 +176,7 @@ class AnteoLoader: iterator += 1 for fs in files: - stringdata = {"title": fs.name, "size": fs.size, "ind": fs.index, + stringdata = {"title": ensure_str(fs.name), "size": fs.size, "ind": fs.index, 'offset': fs.offset} filelist.append(stringdata) return filelist @@ -511,6 +512,7 @@ class AnteoPlayer(xbmc.Player): log('seekTime') log('[AnteoPlayer]: seekTime - '+str(self.seek)) self.seekTime(self.seek) + return True def setup_subs(self): @@ -528,9 +530,8 @@ class AnteoPlayer(xbmc.Player): xbmc.Player().setSubtitles(sub.url) def loop(self): - debug_counter=0 - xbmc.sleep(1000) - + debug_counter = 0 + pause = True with closing( OverlayText(w=OVERLAY_WIDTH, h=OVERLAY_HEIGHT, alignment=XBFONT_CENTER_X | XBFONT_CENTER_Y)) as overlay: with nested(self.attach(overlay.show, self.on_playback_paused), @@ -550,6 +551,10 @@ class AnteoPlayer(xbmc.Player): overlay.text = "\n".join(self._get_status_lines(status, file_status)) self.iterator = int(file_status.progress * 100) + + if pause and self.__settings__.getSetting("pause_onplay") == 'true': + pause = False + xbmc.Player().pause() xbmc.sleep(1000) #if not self.seeding_run and self.iterator == 100 and self.seeding: diff --git a/Content.py b/Content.py index 10b2e33..8d4da4a 100644 --- a/Content.py +++ b/Content.py @@ -2,7 +2,7 @@ ''' Torrenter v2 plugin for XBMC/Kodi Copyright (C) 2012-2015 Vadim Skorba v1 - DiMartino v2 - http://forum.kodi.tv/showthread.php?tid=214366 + https://forums.tvaddons.ag/addon-releases/29224-torrenter-v2.html This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/Core.py b/Core.py index 09597e5..94c05ac 100644 --- a/Core.py +++ b/Core.py @@ -2,7 +2,7 @@ ''' Torrenter v2 plugin for XBMC/Kodi Copyright (C) 2012-2015 Vadim Skorba v1 - DiMartino v2 - http://forum.kodi.tv/showthread.php?tid=214366 + https://forums.tvaddons.ag/addon-releases/29224-torrenter-v2.html This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -260,7 +260,13 @@ class Core: #self.Player = AnteoPlayer(userStorageDirectory=self.userStorageDirectory, torrentUrl=torrentUrl, params=params) log('userStorageDirectory - '+(self.userStorageDirectory)) log('is_writable - '+str(is_writable(self.userStorageDirectory))) - #log('getsize - '+str(os.path.getsize(self.userStorageDirectory))) + + + log('getsize - '+str(os.path.getsize(self.userStorageDirectory))) + + log('getDirectorySizeInBytes - '+str(getDirectorySizeInBytes(self.userStorageDirectory))) + log('getDirectorySizeInGB - '+str(getDirectorySizeInGB(self.userStorageDirectory))) + import stat try: @@ -1366,7 +1372,7 @@ class Core: return def clearStorage(self, params={}): - clearStorage(self.userStorageDirectory) + clearStorage(self.userStorageDirectory, force=True) def magentPlayer(self, params={}): defaultKeyword = params.get('url') diff --git a/Downloader.py b/Downloader.py index 69d2492..3d326f3 100644 --- a/Downloader.py +++ b/Downloader.py @@ -2,7 +2,7 @@ ''' Torrenter v2 plugin for XBMC/Kodi Copyright (C) 2012-2015 Vadim Skorba v1 - DiMartino v2 - http://forum.kodi.tv/showthread.php?tid=214366 + https://forums.tvaddons.ag/addon-releases/29224-torrenter-v2.html This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/Libtorrent.py b/Libtorrent.py index 6925986..c7b9aef 100644 --- a/Libtorrent.py +++ b/Libtorrent.py @@ -2,7 +2,7 @@ ''' Torrenter v2 plugin for XBMC/Kodi Copyright (C) 2012-2015 Vadim Skorba v1 - DiMartino v2 - http://forum.kodi.tv/showthread.php?tid=214366 + https://forums.tvaddons.ag/addon-releases/29224-torrenter-v2.html This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -349,9 +349,13 @@ class Libtorrent: self.session.start_upnp() self.session.start_natpmp() try: - self.session.listen_on(6881, 6891) + port = int(self.__settings__.getSetting('listen_port')) + self.session.listen_on(port, port+10) except: - log('listen_on(6881, 6891) error') + try: + log('listen_on(%d, %d) error' %(port, port+10)) + except: + log('listen_port %s error' %(self.__settings__.getSetting('listen_port'))) pc_config = int(self.__settings__.getSetting('pc_config')) diff --git a/Localization.py b/Localization.py index 2519487..5a16cb8 100644 --- a/Localization.py +++ b/Localization.py @@ -2,7 +2,7 @@ ''' Torrenter v2 plugin for XBMC/Kodi Copyright (C) 2012-2015 Vadim Skorba v1 - DiMartino v2 - http://forum.kodi.tv/showthread.php?tid=214366 + https://forums.tvaddons.ag/addon-releases/29224-torrenter-v2.html This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/Player.py b/Player.py index 5eef40d..20aa2b5 100644 --- a/Player.py +++ b/Player.py @@ -2,7 +2,7 @@ ''' Torrenter v2 plugin for XBMC/Kodi Copyright (C) 2012-2015 Vadim Skorba v1 - DiMartino v2 - http://forum.kodi.tv/showthread.php?tid=214366 + https://forums.tvaddons.ag/addon-releases/29224-torrenter-v2.html This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -336,11 +336,11 @@ class TorrentPlayer(xbmc.Player): xbmc.sleep(1000) if response: - # xbmc.Player().play(path, listitem) - playlist = xbmc.PlayList(xbmc.PLAYLIST_VIDEO) - playlist.clear() - playlist.add(path, listitem) - xbmc.Player().play(playlist) + xbmc.Player().play(path, listitem) + #playlist = xbmc.PlayList(xbmc.PLAYLIST_VIDEO) + #playlist.clear() + #playlist.add(path, listitem) + #xbmc.Player().play(playlist) xbmc.sleep(2000) # very important, do not edit this, podavan return True @@ -401,7 +401,7 @@ class TorrentPlayer(xbmc.Player): def loop(self): debug_counter=0 - xbmc.sleep(1000) + pause = True self.torrent.torrentHandle.force_dht_announce() with closing( OverlayText(w=OVERLAY_WIDTH, h=OVERLAY_HEIGHT, alignment=XBFONT_CENTER_X | XBFONT_CENTER_Y)) as overlay: @@ -420,6 +420,9 @@ class TorrentPlayer(xbmc.Player): overlay.text = "\n".join(self._get_status_lines(status)) # downloadedSize = torrent.torrentHandle.file_progress()[contentId] self.iterator = int(status.progress * 100) + if pause and self.__settings__.getSetting("pause_onplay") == 'true': + pause = False + xbmc.Player().pause() xbmc.sleep(1000) if self.iterator == 100 and self.next_dl: next_contentId_index = self.ids_video.index(str(self.contentId)) + 1 diff --git a/SearcherABC.py b/SearcherABC.py index dc6e937..18638a4 100644 --- a/SearcherABC.py +++ b/SearcherABC.py @@ -2,7 +2,7 @@ ''' Torrenter v2 plugin for XBMC/Kodi Copyright (C) 2012-2015 Vadim Skorba v1 - DiMartino v2 - http://forum.kodi.tv/showthread.php?tid=214366 + https://forums.tvaddons.ag/addon-releases/29224-torrenter-v2.html This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/addon.xml b/addon.xml index dc72f84..e64c5d8 100644 --- a/addon.xml +++ b/addon.xml @@ -1,5 +1,5 @@  - + diff --git a/changelog.txt b/changelog.txt index ec5dd59..020a43f 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,7 +1,11 @@ English changelog at http://bit.ly/1MfSVUP +[B]Version 2.4.5[/B] +[+] Дополнительна секция настроек со специфическими опциями +[+] Минимальный размер хранилища при очищении + [B]Version 2.4.4[/B] -[+] Кнопка редатировать в Истории Поиска +[+] Кнопка редактировать в Истории Поиска [+] Переключатель автоматического запуска следующего эпизода [+] Исправлено ограничение скорости Torrent2HTTP, которое на самом деле измерялось в MB/s, а не Mbit/s [+] Настройки для девайсов/ПК разной мощности у python-libtorrent diff --git a/controlcenter.py b/controlcenter.py index faf0a0c..7371021 100644 --- a/controlcenter.py +++ b/controlcenter.py @@ -2,7 +2,7 @@ ''' Torrenter v2 plugin for XBMC/Kodi Copyright (C) 2012-2015 Vadim Skorba v1 - DiMartino v2 - http://forum.kodi.tv/showthread.php?tid=214366 + https://forums.tvaddons.ag/addon-releases/29224-torrenter-v2.html This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/default.py b/default.py index 7a7d548..09c98a7 100644 --- a/default.py +++ b/default.py @@ -2,7 +2,7 @@ ''' Torrenter v2 plugin for XBMC/Kodi Copyright (C) 2012-2015 Vadim Skorba v1 - DiMartino v2 - http://forum.kodi.tv/showthread.php?tid=214366 + https://forums.tvaddons.ag/addon-releases/29224-torrenter-v2.html This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/functions.py b/functions.py index a9e4c3e..e1d4c75 100644 --- a/functions.py +++ b/functions.py @@ -2,7 +2,7 @@ ''' Torrenter v2 plugin for XBMC/Kodi Copyright (C) 2012-2015 Vadim Skorba v1 - DiMartino v2 - http://forum.kodi.tv/showthread.php?tid=214366 + https://forums.tvaddons.ag/addon-releases/29224-torrenter-v2.html This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -51,55 +51,58 @@ __version__ = __settings__.getAddonInfo('version') __plugin__ = __settings__.getAddonInfo('name') + " v." + __version__ -def clearStorage(userStorageDirectory): +def clearStorage(userStorageDirectory, force = False): userStorageDirectory = decode(userStorageDirectory) #log('[clearStorage]: storage '+str(userStorageDirectory) + os.sep) - if xbmcvfs.exists(userStorageDirectory + os.sep) or os.path.exists(userStorageDirectory): - log('[clearStorage]: storage exists') - import shutil + min_storage_size = __settings__.getSetting("min_storage_size") + storage_size = getDirectorySizeInGB(userStorageDirectory) + if storage_size >= min_storage_size or force: + if xbmcvfs.exists(userStorageDirectory + os.sep) or os.path.exists(userStorageDirectory): + log('[clearStorage]: storage exists') + import shutil - temp = userStorageDirectory.rstrip('Torrenter').rstrip('/\\') - torrents_temp, saved_temp, i = None, None, '' - while not torrents_temp or os.path.exists(torrents_temp) or os.path.exists(saved_temp): - torrents_temp = os.path.join(temp, 'torrents' + str(i)) + os.sep - saved_temp = os.path.join(temp, 'Saved Files' + str(i)) + os.sep - if i=='': - i=0 - else: - i += 1 + temp = userStorageDirectory.rstrip('Torrenter').rstrip('/\\') + torrents_temp, saved_temp, i = None, None, '' + while not torrents_temp or os.path.exists(torrents_temp) or os.path.exists(saved_temp): + torrents_temp = os.path.join(temp, 'torrents' + str(i)) + os.sep + saved_temp = os.path.join(temp, 'Saved Files' + str(i)) + os.sep + if i=='': + i=0 + else: + i += 1 - torrents = os.path.join(userStorageDirectory, 'torrents') - saved = os.path.join(userStorageDirectory, 'Saved Files') - torrents_bool, saved_bool = False, False + torrents = os.path.join(userStorageDirectory, 'torrents') + saved = os.path.join(userStorageDirectory, 'Saved Files') + torrents_bool, saved_bool = False, False - if os.path.exists(torrents): - shutil.move(torrents, torrents_temp) - torrents_bool = True + if os.path.exists(torrents): + shutil.move(torrents, torrents_temp) + torrents_bool = True - if os.path.exists(saved): - shutil.move(saved, saved_temp) - saved_bool = True + if os.path.exists(saved): + shutil.move(saved, saved_temp) + saved_bool = True - shutil.rmtree(userStorageDirectory.encode('utf-8'), ignore_errors=True) - xbmcvfs.mkdir(userStorageDirectory) + shutil.rmtree(userStorageDirectory.encode('utf-8'), ignore_errors=True) + xbmcvfs.mkdir(userStorageDirectory) - if torrents_bool: - shutil.move(torrents_temp, torrents) - if saved_bool: - shutil.move(saved_temp, saved) + if torrents_bool: + shutil.move(torrents_temp, torrents) + if saved_bool: + shutil.move(saved_temp, saved) - showMessage(Localization.localize('Storage'), Localization.localize('Storage has been cleared'), forced=True) + showMessage(Localization.localize('Storage'), Localization.localize('Storage has been cleared'), forced=True) - else: - showMessage(Localization.localize('Storage'), Localization.localize('Does not exists'), forced=True) - log('[clearStorage]: fail storage '+userStorageDirectory + os.sep) + else: + showMessage(Localization.localize('Storage'), Localization.localize('Does not exists'), forced=True) + log('[clearStorage]: fail storage '+userStorageDirectory + os.sep) - try: - DownloadDB().clear() - except Exception, e: - log('[clearStorage]: DownloadDB().clear() failed. '+str(e)) + try: + DownloadDB().clear() + except Exception, e: + log('[clearStorage]: DownloadDB().clear() failed. '+str(e)) - showMessage(Localization.localize('Storage'), Localization.localize('Storage was cleared'), forced=True) + showMessage(Localization.localize('Storage'), Localization.localize('Storage was cleared'), forced=True) def sortcomma(dict, json): @@ -136,9 +139,10 @@ def log(msg): def debug(msg, forced=False): - level=xbmc.LOGDEBUG if getSettingAsBool('debug') and forced: level=xbmc.LOGNOTICE + else: + level=xbmc.LOGDEBUG try: xbmc.log("### [%s]: %s" % (__plugin__,msg,), level=level ) except UnicodeEncodeError: @@ -1993,4 +1997,19 @@ def dump(obj): try: log("'%s':'%s'," % (attr, getattr(obj, attr))) except: - pass \ No newline at end of file + pass + +def getDirectorySizeInBytes(directory): + dir_size = 0 + for (path, dirs, files) in os.walk(directory): + for file in files: + filename = os.path.join(path, file) + try: + dir_size += os.path.getsize(filename) + except: + pass + return dir_size + +def getDirectorySizeInGB(directory): + dir_size = int(getDirectorySizeInBytes(directory)/1024/1024/1024) + return dir_size \ No newline at end of file diff --git a/resources/language/English/strings.xml b/resources/language/English/strings.xml index 92fa7c2..10edd49 100644 --- a/resources/language/English/strings.xml +++ b/resources/language/English/strings.xml @@ -51,14 +51,18 @@ Max. connections (0 - unlimited) Use random ports Port for incoming connections - Pre-buffer amount before start playing, Mb + Pre-buffer amount before start playing (MB) Autoplay next episode (or ask) Device configuration Average/Good PC Below average PC/router + Storage minimum size for auto clear (GB) + Pause video after start Interface P2P Network Advanced + Torrent-client + Hentai (fine-tuning) Save path Call dialog Default @@ -80,7 +84,4 @@ Clear Storage Choose searcher You don't have external searcher. Please install it first. - - - diff --git a/resources/language/Russian/strings.xml b/resources/language/Russian/strings.xml index d77a57d..d02a922 100644 --- a/resources/language/Russian/strings.xml +++ b/resources/language/Russian/strings.xml @@ -51,14 +51,18 @@ Макс. соединений (0 - безлимит) Использовать случайные порты Порт для входящих соединений - Загружаемый объем файла до начала просмотра, Мб + Загружаемый объем файла до начала просмотра (МБ) Автоматически проиграть следующий эпизод (или предложить) Конфигурация устройства Нормальный ПК Плохой ПК/роутер + Минимальный размер хранилища для очистки (ГБ) + Ставить паузу при старте видео Интерфейс P2P Сеть Дополнительные + Торрент-клиент + Hentai (тонкая настр.) Директория для сохранения файлов Вызывать диалог Задать по умолчанию diff --git a/resources/settings.xml b/resources/settings.xml index ec1ff8e..4e3a269 100644 --- a/resources/settings.xml +++ b/resources/settings.xml @@ -18,22 +18,18 @@ - - - - - - - - - - - - - - + + + + + + + + + + - + @@ -64,4 +60,13 @@ + + + + + + + + +