From 178ed24db00dbce6f3d7aee99388491ef6981625 Mon Sep 17 00:00:00 2001 From: WrinklyNinja Date: Tue, 26 Aug 2014 14:31:12 +0100 Subject: [PATCH 01/82] Fixed hover text position flash change. --- resources/report/js/script.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/resources/report/js/script.js b/resources/report/js/script.js index 5689adde..48f187a6 100644 --- a/resources/report/js/script.js +++ b/resources/report/js/script.js @@ -1057,6 +1057,8 @@ function showHoverText(evt) { hoverText.setAttribute('data-target', evt.target.id); var rect = evt.target.getBoundingClientRect(); + hoverText.style.left = (rect.left + evt.target.offsetWidth/2) + 'px'; + hoverText.style.top = (rect.bottom + 10) + 'px'; var dialog = getDialogParent(evt.target); if (dialog) { @@ -1064,8 +1066,6 @@ function showHoverText(evt) { } else { document.body.appendChild(hoverText); } - hoverText.style.left = (rect.left + evt.target.offsetWidth/2) + 'px'; - hoverText.style.top = (rect.bottom + 10) + 'px'; } function hideHoverText(evt) { var hoverText = document.getElementById('hoverText'); From ebb59c13e965b7167aa1aaab5a9ef700e9df8921 Mon Sep 17 00:00:00 2001 From: WrinklyNinja Date: Tue, 26 Aug 2014 14:57:27 +0100 Subject: [PATCH 02/82] Improved plugin menu positioning code. --- resources/report/js/custom.js | 17 +++-------------- 1 file changed, 3 insertions(+), 14 deletions(-) diff --git a/resources/report/js/custom.js b/resources/report/js/custom.js index 9ea30ad4..06b9cd2b 100644 --- a/resources/report/js/custom.js +++ b/resources/report/js/custom.js @@ -539,20 +539,9 @@ var pluginCardProto = Object.create(HTMLElement.prototype, { var main = document.getElementsByTagName('main')[0]; /* Set page position of menu. */ - function getOffset( el, stopEl ) { - var _x = 0; - var _y = 0; - while( el && el != stopEl ) { - _x += el.offsetLeft; - _y += el.offsetTop; - el = el.offsetParent; - } - return { top: _y, left: _x }; - } - var offset = getOffset(evt.target, main); - - menu.style.top = (offset.top + evt.target.offsetHeight + 10) + 'px'; - menu.style.right = (main.offsetWidth - offset.left - evt.target.offsetWidth - 10) + 'px'; + var rect = evt.target.getBoundingClientRect(); + menu.style.right = (main.offsetWidth - (rect.right - main.offsetLeft) - 15) + 'px'; + menu.style.top = (rect.bottom - document.getElementById('container').offsetTop + main.scrollTop + 5) + 'px'; main.appendChild(menu); From a8fc4564778e4c92618d3c20087961b80b344097 Mon Sep 17 00:00:00 2001 From: "Frederik \"Freso\" S. Olesen" Date: Tue, 26 Aug 2014 16:41:18 +0200 Subject: [PATCH 03/82] Ignore temp. files generated by e.g. VIM. --- .gitignore | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.gitignore b/.gitignore index 035a7bb1..0b2bd207 100644 --- a/.gitignore +++ b/.gitignore @@ -26,6 +26,10 @@ *.sql *.sqlite +# Temporary files # +##################3 +*~ + # OS generated files # ###################### .DS_Store From a27b9432e179c3b3b9ae4d782e49cc4ed679a735 Mon Sep 17 00:00:00 2001 From: "Frederik \"Freso\" S. Olesen" Date: Tue, 26 Aug 2014 17:04:29 +0200 Subject: [PATCH 04/82] Fix mix of space vs. tab indentation. Most of the codebase seems to be using space indentation, so normalising towards that. --- .gitattributes | 10 +- docs/LOOT Readme.html | 4 +- docs/licenses/GNU GPL v2 (libgit2).txt | 22 +- src/backend/generators.h | 4 +- src/backend/helpers.cpp | 80 ++-- src/backend/helpers.h | 2 +- src/backend/metadata.cpp | 38 +- src/installer.nsi | 568 ++++++++++++------------- 8 files changed, 364 insertions(+), 364 deletions(-) diff --git a/.gitattributes b/.gitattributes index 412eeda7..0b6acf18 100644 --- a/.gitattributes +++ b/.gitattributes @@ -10,13 +10,13 @@ *.dbproj merge=union # Standard to msysgit -*.doc diff=astextplain -*.DOC diff=astextplain +*.doc diff=astextplain +*.DOC diff=astextplain *.docx diff=astextplain *.DOCX diff=astextplain *.dot diff=astextplain *.DOT diff=astextplain *.pdf diff=astextplain -*.PDF diff=astextplain -*.rtf diff=astextplain -*.RTF diff=astextplain +*.PDF diff=astextplain +*.rtf diff=astextplain +*.RTF diff=astextplain diff --git a/docs/LOOT Readme.html b/docs/LOOT Readme.html index 6d6d54b2..483406c0 100644 --- a/docs/LOOT Readme.html +++ b/docs/LOOT Readme.html @@ -459,7 +459,7 @@ A copy of the license is included in the file named "GNU FDL v1.3.txt".Added: Command line parameter for selecting the game LOOT should run for.
  • Added: Finnish translation.
  • Removed: Support for Windows XP. -
  • Removed: Support for loading BOSS masterlists using the API. This was a leftover from when LOOT was BOSSv3 and backwards compatibility was an issue. +
  • Removed: Support for loading BOSS masterlists using the API. This was a leftover from when LOOT was BOSSv3 and backwards compatibility was an issue.
  • Removed: The ability to open reports in an external browser. This was necessitated by the changes to report generation.
  • Removed: The MSVC 2013 redistributable requirement.
  • Removed: The "None Specified" language option is no longer available: English is the new default. @@ -486,7 +486,7 @@ A copy of the license is included in the file named "GNU FDL v1.3.txt".0.5.0 - 31 March 2014
      -
    • Initial release. +
    • Initial release.
    \ No newline at end of file From 86b81dcafd26c859fe55c5c24c19e5956026d56c Mon Sep 17 00:00:00 2001 From: WrinklyNinja Date: Tue, 26 Aug 2014 23:22:27 +0100 Subject: [PATCH 10/82] Implemented custom progress bar. CEF won't animate the `` value pseudo-element, though it works fine in Chrome, so I had to roll my own. Part of #246. --- resources/report/css/style.css | 17 +++++++++++++---- resources/report/js/script.js | 2 +- resources/report/report.html | 9 +++++++-- 3 files changed, 21 insertions(+), 7 deletions(-) diff --git a/resources/report/css/style.css b/resources/report/css/style.css index 2e0146e4..50a74bf9 100644 --- a/resources/report/css/style.css +++ b/resources/report/css/style.css @@ -419,12 +419,16 @@ input:valid { box-shadow:0 0 3px 0px rgba(0,0,0,0.5); padding: 2px 5px; } -progress { +progress, .progress { /* Reset the default appearance */ -webkit-appearance: none; width: 250px; height: 20px; display: block; + margin: 0 auto; +} +#progressDialog > h1 { + font-size: 1.5em; } @-webkit-keyframes indeterminate { @@ -432,11 +436,16 @@ progress { 100% { width: 100% } } -progress::-webkit-progress-bar { +progress::-webkit-progress-bar, .progress.bar { background-color: #eee; border-radius: 2px; box-shadow: 0 2px 5px rgba(0, 0, 0, 0.25) inset; } -progress::-webkit-progress-value { - -webkit-animation: indeterminate 5s linear 0 infinite alternate; +progress::-webkit-progress-value, .progress .value { + height: 100%; + background-color: green; + -webkit-animation: indeterminate 2s linear 0 infinite alternate paused; +} +#progressDialog[open] > .progress > .value { + -webkit-animation-play-state: running; } \ No newline at end of file diff --git a/resources/report/js/script.js b/resources/report/js/script.js index 776ba31e..3ab20846 100644 --- a/resources/report/js/script.js +++ b/resources/report/js/script.js @@ -759,7 +759,7 @@ function updateProgressDialog(message) { progressDialog.getElementsByTagName('h1')[0].textContent = message; } function sortPlugins(evt) { - updateProgressDialog('LOOT Working...'); + updateProgressDialog('Sorting plugins...'); toggleProgressDialog(); if (loot.settings.updateMasterlist) { updateMasterlist(evt); diff --git a/resources/report/report.html b/resources/report/report.html index aaf284ce..3d62a37c 100644 --- a/resources/report/report.html +++ b/resources/report/report.html @@ -566,8 +566,13 @@ along with LOOT. If not, see <http://www.gnu.org/licenses/>. - -

    + +
    +
    +
    +

    Calculating the last digit of π...

    From ac6c28364b765a278d062f07b45f63cdf398447a Mon Sep 17 00:00:00 2001 From: WrinklyNinja Date: Tue, 26 Aug 2014 23:40:39 +0100 Subject: [PATCH 11/82] Masterlist update is now non-UI-blocking. For #246. --- resources/report/js/script.js | 23 +++-- src/gui/handler.cpp | 189 +++++++++++++++++----------------- src/gui/handler.h | 2 +- 3 files changed, 111 insertions(+), 103 deletions(-) diff --git a/resources/report/js/script.js b/resources/report/js/script.js index 3ab20846..8aade6f1 100644 --- a/resources/report/js/script.js +++ b/resources/report/js/script.js @@ -359,6 +359,7 @@ function processCefError(err) { /* Error.stack seems to be Chromium-specific. It gives a lot more useful info than just the error message. */ console.log(err.stack); + closeProgressDialog(); showMessageBox('error', 'Error', err.message); } @@ -661,8 +662,11 @@ function openReadme(evt) { loot.query('openReadme').catch(processCefError); } function updateMasterlist(evt) { + updateProgressDialog('Updating masterlist...'); + openProgressDialog(); loot.query('updateMasterlist').then(JSON.parse).then(function(result){ if (result == null) { + closeProgressDialog(); return; } /* Update JS variables. */ @@ -683,6 +687,7 @@ function updateMasterlist(evt) { } } }); + closeProgressDialog(); }).catch(processCefError); } function sortUIElements(pluginNames) { @@ -746,11 +751,9 @@ function sortUIElements(pluginNames) { lastCard = card; }); } -function toggleProgressDialog() { +function openProgressDialog() { var progressDialog = document.getElementById('progressDialog'); - if (progressDialog.open) { - progressDialog.close(); - } else { + if (!progressDialog.open) { progressDialog.showModal(); } } @@ -758,12 +761,18 @@ function updateProgressDialog(message) { var progressDialog = document.getElementById('progressDialog'); progressDialog.getElementsByTagName('h1')[0].textContent = message; } +function closeProgressDialog() { + var progressDialog = document.getElementById('progressDialog'); + if (progressDialog.open) { + progressDialog.close(); + } +} function sortPlugins(evt) { - updateProgressDialog('Sorting plugins...'); - toggleProgressDialog(); if (loot.settings.updateMasterlist) { updateMasterlist(evt); } + updateProgressDialog('Sorting plugins...'); + openProgressDialog(); loot.query('sortPlugins').then(JSON.parse).then(function(result){ if (result) { var loadOrder = []; @@ -800,7 +809,7 @@ function sortPlugins(evt) { hideElement(document.getElementById('sortButton')); showElement(document.getElementById('applySortButton')); showElement(document.getElementById('cancelSortButton')); - toggleProgressDialog(); + closeProgressDialog(); } }).catch(processCefError); } diff --git a/src/gui/handler.cpp b/src/gui/handler.cpp index eb3fa58d..9d75d7cc 100644 --- a/src/gui/handler.cpp +++ b/src/gui/handler.cpp @@ -166,18 +166,7 @@ namespace loot { return true; } else if (request == "updateMasterlist") { - try { - callback->Success(UpdateMasterlist()); - } - catch (error &e) { - BOOST_LOG_TRIVIAL(error) << "Failed to update the masterlist. " << e.what(); - callback->Failure(e.code(), e.what()); - } - catch (exception &e) { - BOOST_LOG_TRIVIAL(error) << "Failed to update the masterlist. " << e.what(); - callback->Failure(-1, e.what()); - } - return true; + return CefPostTask(TID_FILE, base::Bind(&Handler::UpdateMasterlist, base::Unretained(this), callback)); } else if (request == "sortPlugins") { return CefPostTask(TID_FILE, base::Bind(&Handler::SortPlugins, base::Unretained(this), callback)); @@ -728,93 +717,103 @@ namespace loot { return JSON::stringify(gameNode); } - std::string Handler::UpdateMasterlist() { - BOOST_LOG_TRIVIAL(debug) << "Updating and parsing masterlist."; - - //Set language. - unsigned int language; - if (g_app_state.GetSettings()["language"]) - language = Language(g_app_state.GetSettings()["language"].as()).Code(); - else - language = Language::any; - BOOST_LOG_TRIVIAL(info) << "Using message language: " << Language(language).Name(); - - // Update / parse masterlist. - bool wasChanged = true; + void Handler::UpdateMasterlist(CefRefPtr callback) { try { - wasChanged = g_app_state.CurrentGame().masterlist.Load(g_app_state.CurrentGame(), language); - } - catch (loot::error &e) { - if (e.code() == loot::error::ok) { - // There was a parsing error, but roll-back was successful, so the process - // should still complete. - g_app_state.CurrentGame().masterlist.messages.push_back(Message(Message::error, e.what())); - wasChanged = true; + BOOST_LOG_TRIVIAL(debug) << "Updating and parsing masterlist."; + + //Set language. + unsigned int language; + if (g_app_state.GetSettings()["language"]) + language = Language(g_app_state.GetSettings()["language"].as()).Code(); + else + language = Language::any; + BOOST_LOG_TRIVIAL(info) << "Using message language: " << Language(language).Name(); + + // Update / parse masterlist. + bool wasChanged = true; + try { + wasChanged = g_app_state.CurrentGame().masterlist.Load(g_app_state.CurrentGame(), language); + } + catch (loot::error &e) { + if (e.code() == loot::error::ok) { + // There was a parsing error, but roll-back was successful, so the process + // should still complete. + g_app_state.CurrentGame().masterlist.messages.push_back(Message(Message::error, e.what())); + wasChanged = true; + } + else + throw e; + } + + // Now regenerate the JS-side masterlist data if the masterlist was changed. + if (wasChanged) { + // The data structure is to be set as 'loot.game'. + YAML::Node gameNode; + + // Store the masterlist revision and date. + gameNode["masterlist"]["revision"] = g_app_state.CurrentGame().masterlist.GetRevision(g_app_state.CurrentGame().MasterlistPath()); + gameNode["masterlist"]["date"] = g_app_state.CurrentGame().masterlist.GetDate(g_app_state.CurrentGame().MasterlistPath()); + + for (const auto& pluginPair : g_app_state.CurrentGame().plugins) { + Plugin mlistPlugin(pluginPair.second); + mlistPlugin.MergeMetadata(g_app_state.CurrentGame().masterlist.FindPlugin(pluginPair.second)); + + YAML::Node pluginNode; + if (!mlistPlugin.HasNameOnly()) { + // Now add the masterlist metadata to the pluginNode. + pluginNode["masterlist"]["after"] = mlistPlugin.LoadAfter(); + pluginNode["masterlist"]["req"] = mlistPlugin.Reqs(); + pluginNode["masterlist"]["inc"] = mlistPlugin.Incs(); + pluginNode["masterlist"]["msg"] = mlistPlugin.Messages(); + pluginNode["masterlist"]["tag"] = mlistPlugin.Tags(); + pluginNode["masterlist"]["dirty"] = mlistPlugin.DirtyInfo(); + } + + // Now merge masterlist and userlist metadata and evaluate, + // putting any resulting metadata into the base of the pluginNode. + YAML::Node derivedNode = GenerateDerivedMetadata(pluginPair.second.Name()); + + for (auto it = derivedNode.begin(); it != derivedNode.end(); ++it) { + const string key = it->first.as(); + pluginNode[key] = it->second; + } + + gameNode["plugins"].push_back(pluginNode); + } + + //Evaluate any conditions in the global messages. + BOOST_LOG_TRIVIAL(debug) << "Evaluating global message conditions."; + list messages = g_app_state.CurrentGame().masterlist.messages; + try { + list::iterator it = messages.begin(); + while (it != messages.end()) { + if (!it->EvalCondition(g_app_state.CurrentGame(), language)) + it = messages.erase(it); + else + ++it; + } + } + catch (std::exception& e) { + BOOST_LOG_TRIVIAL(error) << "A global message contains a condition that could not be evaluated. Details: " << e.what(); + messages.push_back(Message(Message::error, (format(loc::translate("A global message contains a condition that could not be evaluated. Details: %1%")) % e.what()).str())); + } + + // Now store global messages from masterlist. + gameNode["globalMessages"] = messages; + + callback->Success(JSON::stringify(gameNode)); } else - throw e; + callback->Success("null"); } - - // Now regenerate the JS-side masterlist data if the masterlist was changed. - if (wasChanged) { - // The data structure is to be set as 'loot.game'. - YAML::Node gameNode; - - // Store the masterlist revision and date. - gameNode["masterlist"]["revision"] = g_app_state.CurrentGame().masterlist.GetRevision(g_app_state.CurrentGame().MasterlistPath()); - gameNode["masterlist"]["date"] = g_app_state.CurrentGame().masterlist.GetDate(g_app_state.CurrentGame().MasterlistPath()); - - for (const auto& pluginPair : g_app_state.CurrentGame().plugins) { - Plugin mlistPlugin(pluginPair.second); - mlistPlugin.MergeMetadata(g_app_state.CurrentGame().masterlist.FindPlugin(pluginPair.second)); - - YAML::Node pluginNode; - if (!mlistPlugin.HasNameOnly()) { - // Now add the masterlist metadata to the pluginNode. - pluginNode["masterlist"]["after"] = mlistPlugin.LoadAfter(); - pluginNode["masterlist"]["req"] = mlistPlugin.Reqs(); - pluginNode["masterlist"]["inc"] = mlistPlugin.Incs(); - pluginNode["masterlist"]["msg"] = mlistPlugin.Messages(); - pluginNode["masterlist"]["tag"] = mlistPlugin.Tags(); - pluginNode["masterlist"]["dirty"] = mlistPlugin.DirtyInfo(); - } - - // Now merge masterlist and userlist metadata and evaluate, - // putting any resulting metadata into the base of the pluginNode. - YAML::Node derivedNode = GenerateDerivedMetadata(pluginPair.second.Name()); - - for (auto it = derivedNode.begin(); it != derivedNode.end(); ++it) { - const string key = it->first.as(); - pluginNode[key] = it->second; - } - - gameNode["plugins"].push_back(pluginNode); - } - - //Evaluate any conditions in the global messages. - BOOST_LOG_TRIVIAL(debug) << "Evaluating global message conditions."; - list messages = g_app_state.CurrentGame().masterlist.messages; - try { - list::iterator it = messages.begin(); - while (it != messages.end()) { - if (!it->EvalCondition(g_app_state.CurrentGame(), language)) - it = messages.erase(it); - else - ++it; - } - } - catch (std::exception& e) { - BOOST_LOG_TRIVIAL(error) << "A global message contains a condition that could not be evaluated. Details: " << e.what(); - messages.push_back(Message(Message::error, (format(loc::translate("A global message contains a condition that could not be evaluated. Details: %1%")) % e.what()).str())); - } - - // Now store global messages from masterlist. - gameNode["globalMessages"] = messages; - - return JSON::stringify(gameNode); + catch (error &e) { + BOOST_LOG_TRIVIAL(error) << "Failed to update the masterlist. " << e.what(); + callback->Failure(e.code(), e.what()); + } + catch (exception &e) { + BOOST_LOG_TRIVIAL(error) << "Failed to update the masterlist. " << e.what(); + callback->Failure(-1, e.what()); } - else - return "null"; } std::string Handler::ClearAllMetadata() { @@ -843,7 +842,7 @@ namespace loot { return "[]"; } - void Handler::SortPlugins(CefRefPtr callback) { + void Handler::SortPlugins(CefRefPtr callback) { //Set language. unsigned int language; if (g_app_state.GetSettings()["language"]) diff --git a/src/gui/handler.h b/src/gui/handler.h index 8b556b5e..bfa8499d 100644 --- a/src/gui/handler.h +++ b/src/gui/handler.h @@ -57,7 +57,7 @@ namespace loot { std::string GetGameTypes(); std::string GetInstalledGames(); std::string GetGameData(); - std::string UpdateMasterlist(); + void UpdateMasterlist(CefRefPtr callback); std::string ClearAllMetadata(); void SortPlugins(CefRefPtr callback); From 65fa6b34cc75c9f9b790e6f1b123f0185e414c58 Mon Sep 17 00:00:00 2001 From: WrinklyNinja Date: Tue, 26 Aug 2014 23:43:32 +0100 Subject: [PATCH 12/82] Fixed sorting skipping repeated plugin loading. While it does lead to almost instantaneous sorting, the plugins may have changed since they were last loaded, and there's no way to tell currently, so load them all to be safe. --- src/gui/handler.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/gui/handler.cpp b/src/gui/handler.cpp index 9d75d7cc..6c0bb338 100644 --- a/src/gui/handler.cpp +++ b/src/gui/handler.cpp @@ -851,9 +851,8 @@ namespace loot { language = Language::any; BOOST_LOG_TRIVIAL(info) << "Using message language: " << Language(language).Name(); - // Check if the plugins have been fully loaded, and if not load all plugins. - if (!g_app_state.CurrentGame().HasBeenLoaded()) - g_app_state.CurrentGame().LoadPlugins(false); + // Always reload all the plugins. + g_app_state.CurrentGame().LoadPlugins(false); //Sort plugins into their load order. list plugins = g_app_state.CurrentGame().Sort(language, [](const string& message){}); From 2f5d51071a9e4525ae915f5247b3307f0890a1ec Mon Sep 17 00:00:00 2001 From: WrinklyNinja Date: Tue, 26 Aug 2014 23:56:14 +0100 Subject: [PATCH 13/82] Getting game data no longer blocks UI. Progress dialogs added for initialisation, game change and window refocus refresh. Part of #246. --- resources/report/js/script.js | 13 +- src/gui/handler.cpp | 302 +++++++++++++++++----------------- src/gui/handler.h | 2 +- 3 files changed, 163 insertions(+), 154 deletions(-) diff --git a/resources/report/js/script.js b/resources/report/js/script.js index 8aade6f1..804932de 100644 --- a/resources/report/js/script.js +++ b/resources/report/js/script.js @@ -561,6 +561,8 @@ function changeGame(evt) { loot.games[index].masterlist = loot.game.masterlist; loot.games[index].plugins = loot.game.plugins; + updateProgressDialog('Loading game data...'); + openProgressDialog(); /* Now send off a CEF query with the folder name of the new game. */ var request = JSON.stringify({ @@ -594,7 +596,7 @@ function changeGame(evt) { var gameInfo = JSON.parse(result, jsonToPlugin); } catch (e) { console.log(e); - console.log('getGameData response: ' + result); + console.log('changeGame response: ' + result); } /* This may not be the first time loading this game this instance of @@ -656,6 +658,8 @@ function changeGame(evt) { /* Reapply previously active filters. */ applyFilters(); + + closeProgressDialog(); }).catch(processCefError); } function openReadme(evt) { @@ -1249,6 +1253,8 @@ function initVars() { parallelPromises.push(loot.query('getGameData')); } + updateProgressDialog('Initialising user interface...'); + openProgressDialog(); Promise.all(parallelPromises).then(function(results) { try { loot.gameTypes = JSON.parse(results[0]); @@ -1298,12 +1304,15 @@ function initVars() { document.getElementById('settingsButton').click(); } + closeProgressDialog(); }).catch(processCefError); }).catch(processCefError); } function onFocus() { /* Send a query for updated load order and plugin header info. */ + updateProgressDialog('Refreshing data...'); + openProgressDialog(); loot.query('getGameData').then(function(result){ /* Parse the data sent from C++. */ try { @@ -1368,6 +1377,8 @@ function onFocus() { /* Reapply filters. */ applyFilters(); + + closeProgressDialog(); }).catch(processCefError); } function checkFocus(){ diff --git a/src/gui/handler.cpp b/src/gui/handler.cpp index 6c0bb338..53b2bc83 100644 --- a/src/gui/handler.cpp +++ b/src/gui/handler.cpp @@ -126,18 +126,7 @@ namespace loot { #ifdef _WIN32 SetWindowText(handle, ToWinWide("LOOT: " + g_app_state.CurrentGame().Name()).c_str()); #endif - try { - callback->Success(GetGameData()); - } - catch (error &e) { - BOOST_LOG_TRIVIAL(error) << "Failed to get game data. " << e.what(); - callback->Failure(e.code(), e.what()); - } - catch (exception &e) { - BOOST_LOG_TRIVIAL(error) << "Failed to get game data. " << e.what(); - callback->Failure(-1, e.what()); - } - return true; + return CefPostTask(TID_FILE, base::Bind(&Handler::GetGameData, base::Unretained(this), callback)); } else if (request == "cancelFind") { browser->GetHost()->StopFinding(true); @@ -220,8 +209,7 @@ namespace loot { #ifdef _WIN32 SetWindowText(handle, ToWinWide("LOOT: " + g_app_state.CurrentGame().Name()).c_str()); #endif - - callback->Success(GetGameData()); + CefPostTask(TID_FILE, base::Bind(&Handler::GetGameData, base::Unretained(this), callback)); } catch (loot::error &e) { BOOST_LOG_TRIVIAL(error) << "Failed to change game. Details: " << e.what(); @@ -561,160 +549,170 @@ namespace loot { return "[]"; } - std::string Handler::GetGameData() { - /* GetGameData() can be called for initialising the UI for a game for the first time - in a session, or it can be called when changing to a game that has previously been - active. In the first case, all data should be loaded, but in the second, only load - order and plugin header info should be re-loaded. - Determine which case it is by checking to see if the game's plugins object is empty. - */ - BOOST_LOG_TRIVIAL(info) << "Getting data specific to LOOT's active game."; - // Get masterlist revision info and parse if it exists. Also get plugin headers info and parse userlist if it exists. + void Handler::GetGameData(CefRefPtr callback) { + try { + /* GetGameData() can be called for initialising the UI for a game for the first time + in a session, or it can be called when changing to a game that has previously been + active. In the first case, all data should be loaded, but in the second, only load + order and plugin header info should be re-loaded. + Determine which case it is by checking to see if the game's plugins object is empty. + */ + BOOST_LOG_TRIVIAL(info) << "Getting data specific to LOOT's active game."; + // Get masterlist revision info and parse if it exists. Also get plugin headers info and parse userlist if it exists. - bool isFirstLoad = g_app_state.CurrentGame().plugins.empty(); - g_app_state.CurrentGame().LoadPlugins(true); + bool isFirstLoad = g_app_state.CurrentGame().plugins.empty(); + g_app_state.CurrentGame().LoadPlugins(true); - //Sort plugins into their load order. - list installed; - list loadOrder; - g_app_state.CurrentGame().GetLoadOrder(loadOrder); - for (const auto &pluginName : loadOrder) { - const auto pos = g_app_state.CurrentGame().plugins.find(boost::locale::to_lower(pluginName)); + //Sort plugins into their load order. + list installed; + list loadOrder; + g_app_state.CurrentGame().GetLoadOrder(loadOrder); + for (const auto &pluginName : loadOrder) { + const auto pos = g_app_state.CurrentGame().plugins.find(boost::locale::to_lower(pluginName)); - if (pos != g_app_state.CurrentGame().plugins.end()) - installed.push_back(pos->second); - } - - if (isFirstLoad) { - //Parse masterlist, don't update it. - if (fs::exists(g_app_state.CurrentGame().MasterlistPath())) { - BOOST_LOG_TRIVIAL(debug) << "Parsing masterlist."; - try { - g_app_state.CurrentGame().masterlist.MetadataList::Load(g_app_state.CurrentGame().MasterlistPath()); - } - catch (exception &e) { - g_app_state.CurrentGame().masterlist.messages.push_back(Message(Message::error, string("An error occurred while parsing the masterlist: ") + e.what())); - } + if (pos != g_app_state.CurrentGame().plugins.end()) + installed.push_back(pos->second); } - //Parse userlist. - if (fs::exists(g_app_state.CurrentGame().UserlistPath())) { - BOOST_LOG_TRIVIAL(debug) << "Parsing userlist."; - try { - g_app_state.CurrentGame().userlist.Load(g_app_state.CurrentGame().UserlistPath()); - } - catch (exception &e) { - g_app_state.CurrentGame().userlist.messages.push_back(Message(Message::error, string("An error occurred while parsing the userlist: ") + e.what())); - } - } - } - - // Now convert to a single object that can be turned into a JSON string - //--------------------------------------------------------------------- - - // The data structure is to be set as 'loot.game'. - YAML::Node gameNode; - - // ID the game using its folder value. - gameNode["folder"] = g_app_state.CurrentGame().FolderName(); - - if (isFirstLoad) { - // Store the masterlist revision and date. - gameNode["masterlist"]["revision"] = g_app_state.CurrentGame().masterlist.GetRevision(g_app_state.CurrentGame().MasterlistPath()); - gameNode["masterlist"]["date"] = g_app_state.CurrentGame().masterlist.GetDate(g_app_state.CurrentGame().MasterlistPath()); - } - - // Now store plugin data. - for (const auto& plugin : installed) { - /* Each plugin has members while hold its raw masterlist and userlist data for - the editor, and also processed data for the main display. - */ - YAML::Node pluginNode; - // Find the masterlist metadata for this plugin. Treat Bash Tags from the plugin - // description as part of it. - BOOST_LOG_TRIVIAL(trace) << "Getting masterlist metadata for: " << plugin.Name(); - Plugin mlistPlugin(plugin); - mlistPlugin.MergeMetadata(g_app_state.CurrentGame().masterlist.FindPlugin(plugin)); - - // Now do the same again for any userlist data. - BOOST_LOG_TRIVIAL(trace) << "Getting userlist metadata for: " << plugin.Name(); - Plugin ulistPlugin(g_app_state.CurrentGame().userlist.FindPlugin(plugin)); - - pluginNode["__type"] = "Plugin"; // For conversion back into a JS typed object. - pluginNode["name"] = plugin.Name(); - pluginNode["isActive"] = g_app_state.CurrentGame().IsActive(plugin.Name()); - pluginNode["isDummy"] = false; // Set to false for now because we just don't know yet. - pluginNode["loadsBSA"] = plugin.LoadsBSA(g_app_state.CurrentGame()); - pluginNode["crc"] = IntToHexString(plugin.Crc()); - pluginNode["version"] = plugin.Version(); - if (isFirstLoad) { - if (!mlistPlugin.HasNameOnly()) { - // Now add the masterlist metadata to the pluginNode. - pluginNode["masterlist"]["after"] = mlistPlugin.LoadAfter(); - pluginNode["masterlist"]["req"] = mlistPlugin.Reqs(); - pluginNode["masterlist"]["inc"] = mlistPlugin.Incs(); - pluginNode["masterlist"]["msg"] = mlistPlugin.Messages(); - pluginNode["masterlist"]["tag"] = mlistPlugin.Tags(); - pluginNode["masterlist"]["dirty"] = mlistPlugin.DirtyInfo(); + //Parse masterlist, don't update it. + if (fs::exists(g_app_state.CurrentGame().MasterlistPath())) { + BOOST_LOG_TRIVIAL(debug) << "Parsing masterlist."; + try { + g_app_state.CurrentGame().masterlist.MetadataList::Load(g_app_state.CurrentGame().MasterlistPath()); + } + catch (exception &e) { + g_app_state.CurrentGame().masterlist.messages.push_back(Message(Message::error, string("An error occurred while parsing the masterlist: ") + e.what())); + } } - if (!ulistPlugin.HasNameOnly()) { - // Now add the userlist metadata to the pluginNode. - pluginNode["userlist"]["enabled"] = ulistPlugin.Enabled(); - pluginNode["userlist"]["after"] = ulistPlugin.LoadAfter(); - pluginNode["userlist"]["req"] = ulistPlugin.Reqs(); - pluginNode["userlist"]["inc"] = ulistPlugin.Incs(); - pluginNode["userlist"]["msg"] = ulistPlugin.Messages(); - pluginNode["userlist"]["tag"] = ulistPlugin.Tags(); - pluginNode["userlist"]["dirty"] = ulistPlugin.DirtyInfo(); + //Parse userlist. + if (fs::exists(g_app_state.CurrentGame().UserlistPath())) { + BOOST_LOG_TRIVIAL(debug) << "Parsing userlist."; + try { + g_app_state.CurrentGame().userlist.Load(g_app_state.CurrentGame().UserlistPath()); + } + catch (exception &e) { + g_app_state.CurrentGame().userlist.messages.push_back(Message(Message::error, string("An error occurred while parsing the userlist: ") + e.what())); + } } } - // Now merge masterlist and userlist metadata and evaluate, - // putting any resulting metadata into the base of the pluginNode. - YAML::Node derivedNode = GenerateDerivedMetadata(plugin, mlistPlugin, ulistPlugin); + // Now convert to a single object that can be turned into a JSON string + //--------------------------------------------------------------------- - for (auto it = derivedNode.begin(); it != derivedNode.end(); ++it) { - const string key = it->first.as(); - pluginNode[key] = it->second; + // The data structure is to be set as 'loot.game'. + YAML::Node gameNode; + + // ID the game using its folder value. + gameNode["folder"] = g_app_state.CurrentGame().FolderName(); + + if (isFirstLoad) { + // Store the masterlist revision and date. + gameNode["masterlist"]["revision"] = g_app_state.CurrentGame().masterlist.GetRevision(g_app_state.CurrentGame().MasterlistPath()); + gameNode["masterlist"]["date"] = g_app_state.CurrentGame().masterlist.GetDate(g_app_state.CurrentGame().MasterlistPath()); } - gameNode["plugins"].push_back(pluginNode); + // Now store plugin data. + for (const auto& plugin : installed) { + /* Each plugin has members while hold its raw masterlist and userlist data for + the editor, and also processed data for the main display. + */ + YAML::Node pluginNode; + // Find the masterlist metadata for this plugin. Treat Bash Tags from the plugin + // description as part of it. + BOOST_LOG_TRIVIAL(trace) << "Getting masterlist metadata for: " << plugin.Name(); + Plugin mlistPlugin(plugin); + mlistPlugin.MergeMetadata(g_app_state.CurrentGame().masterlist.FindPlugin(plugin)); + + // Now do the same again for any userlist data. + BOOST_LOG_TRIVIAL(trace) << "Getting userlist metadata for: " << plugin.Name(); + Plugin ulistPlugin(g_app_state.CurrentGame().userlist.FindPlugin(plugin)); + + pluginNode["__type"] = "Plugin"; // For conversion back into a JS typed object. + pluginNode["name"] = plugin.Name(); + pluginNode["isActive"] = g_app_state.CurrentGame().IsActive(plugin.Name()); + pluginNode["isDummy"] = false; // Set to false for now because we just don't know yet. + pluginNode["loadsBSA"] = plugin.LoadsBSA(g_app_state.CurrentGame()); + pluginNode["crc"] = IntToHexString(plugin.Crc()); + pluginNode["version"] = plugin.Version(); + + if (isFirstLoad) { + if (!mlistPlugin.HasNameOnly()) { + // Now add the masterlist metadata to the pluginNode. + pluginNode["masterlist"]["after"] = mlistPlugin.LoadAfter(); + pluginNode["masterlist"]["req"] = mlistPlugin.Reqs(); + pluginNode["masterlist"]["inc"] = mlistPlugin.Incs(); + pluginNode["masterlist"]["msg"] = mlistPlugin.Messages(); + pluginNode["masterlist"]["tag"] = mlistPlugin.Tags(); + pluginNode["masterlist"]["dirty"] = mlistPlugin.DirtyInfo(); + } + + if (!ulistPlugin.HasNameOnly()) { + // Now add the userlist metadata to the pluginNode. + pluginNode["userlist"]["enabled"] = ulistPlugin.Enabled(); + pluginNode["userlist"]["after"] = ulistPlugin.LoadAfter(); + pluginNode["userlist"]["req"] = ulistPlugin.Reqs(); + pluginNode["userlist"]["inc"] = ulistPlugin.Incs(); + pluginNode["userlist"]["msg"] = ulistPlugin.Messages(); + pluginNode["userlist"]["tag"] = ulistPlugin.Tags(); + pluginNode["userlist"]["dirty"] = ulistPlugin.DirtyInfo(); + } + } + + // Now merge masterlist and userlist metadata and evaluate, + // putting any resulting metadata into the base of the pluginNode. + YAML::Node derivedNode = GenerateDerivedMetadata(plugin, mlistPlugin, ulistPlugin); + + for (auto it = derivedNode.begin(); it != derivedNode.end(); ++it) { + const string key = it->first.as(); + pluginNode[key] = it->second; + } + + gameNode["plugins"].push_back(pluginNode); + } + + if (isFirstLoad) { + //Set language. + unsigned int language; + if (g_app_state.GetSettings()["language"]) + language = Language(g_app_state.GetSettings()["language"].as()).Code(); + else + language = Language::any; + BOOST_LOG_TRIVIAL(info) << "Using message language: " << Language(language).Name(); + + //Evaluate any conditions in the global messages. + BOOST_LOG_TRIVIAL(debug) << "Evaluating global message conditions."; + list messages = g_app_state.CurrentGame().masterlist.messages; + messages.insert(messages.end(), g_app_state.CurrentGame().userlist.messages.begin(), g_app_state.CurrentGame().userlist.messages.end()); + try { + list::iterator it = messages.begin(); + while (it != messages.end()) { + if (!it->EvalCondition(g_app_state.CurrentGame(), language)) + it = messages.erase(it); + else + ++it; + } + } + catch (std::exception& e) { + BOOST_LOG_TRIVIAL(error) << "A global message contains a condition that could not be evaluated. Details: " << e.what(); + messages.push_back(Message(Message::error, (format(loc::translate("A global message contains a condition that could not be evaluated. Details: %1%")) % e.what()).str())); + } + + // Now store global messages from masterlist. + gameNode["globalMessages"] = messages; + } + + callback->Success(JSON::stringify(gameNode)); } - - if (isFirstLoad) { - //Set language. - unsigned int language; - if (g_app_state.GetSettings()["language"]) - language = Language(g_app_state.GetSettings()["language"].as()).Code(); - else - language = Language::any; - BOOST_LOG_TRIVIAL(info) << "Using message language: " << Language(language).Name(); - - //Evaluate any conditions in the global messages. - BOOST_LOG_TRIVIAL(debug) << "Evaluating global message conditions."; - list messages = g_app_state.CurrentGame().masterlist.messages; - messages.insert(messages.end(), g_app_state.CurrentGame().userlist.messages.begin(), g_app_state.CurrentGame().userlist.messages.end()); - try { - list::iterator it = messages.begin(); - while (it != messages.end()) { - if (!it->EvalCondition(g_app_state.CurrentGame(), language)) - it = messages.erase(it); - else - ++it; - } - } - catch (std::exception& e) { - BOOST_LOG_TRIVIAL(error) << "A global message contains a condition that could not be evaluated. Details: " << e.what(); - messages.push_back(Message(Message::error, (format(loc::translate("A global message contains a condition that could not be evaluated. Details: %1%")) % e.what()).str())); - } - - // Now store global messages from masterlist. - gameNode["globalMessages"] = messages; + catch (loot::error &e) { + BOOST_LOG_TRIVIAL(error) << "Failed to change game. Details: " << e.what(); + callback->Failure(e.code(), string("Failed to change game. Details: ") + e.what()); + } + catch (std::exception& e) { + BOOST_LOG_TRIVIAL(error) << "Failed to change game. Details: " << e.what(); + callback->Failure(-1, string("Failed to change game. Details: ") + e.what()); } - - return JSON::stringify(gameNode); } void Handler::UpdateMasterlist(CefRefPtr callback) { diff --git a/src/gui/handler.h b/src/gui/handler.h index bfa8499d..d4d72978 100644 --- a/src/gui/handler.h +++ b/src/gui/handler.h @@ -56,7 +56,7 @@ namespace loot { std::string GetLanguages(); std::string GetGameTypes(); std::string GetInstalledGames(); - std::string GetGameData(); + void GetGameData(CefRefPtr callback); void UpdateMasterlist(CefRefPtr callback); std::string ClearAllMetadata(); void SortPlugins(CefRefPtr callback); From ae7c731b9048bba1d473e6bcd3b96b3c2926a582 Mon Sep 17 00:00:00 2001 From: WrinklyNinja Date: Wed, 27 Aug 2014 00:23:52 +0100 Subject: [PATCH 14/82] Tidied up handler.cpp includes. --- src/gui/handler.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/gui/handler.cpp b/src/gui/handler.cpp index 53b2bc83..759a2502 100644 --- a/src/gui/handler.cpp +++ b/src/gui/handler.cpp @@ -34,7 +34,7 @@ #include #include #include -#include "include/wrapper/cef_closure_task.h" +#include #include #include @@ -43,7 +43,6 @@ #include #include -#include using namespace std; From f34e6edb7738d0e8ace5cfc9d1fbff5607e749b9 Mon Sep 17 00:00:00 2001 From: WrinklyNinja Date: Wed, 27 Aug 2014 00:34:46 +0100 Subject: [PATCH 15/82] Death to trailing whitespace! Sorry about that... --- src/backend/game.h | 6 +++--- src/backend/git.cpp | 6 ++---- src/backend/metadata.cpp | 1 - src/backend/metadata.h | 2 +- src/gui/app.cpp | 7 ++++--- src/gui/app.h | 4 ++-- src/gui/handler.cpp | 14 +++++++------- src/gui/handler.h | 10 +++++----- src/gui/main_win.cpp | 2 +- 9 files changed, 25 insertions(+), 27 deletions(-) diff --git a/src/backend/game.h b/src/backend/game.h index e303002c..9d282fcf 100644 --- a/src/backend/game.h +++ b/src/backend/game.h @@ -41,7 +41,7 @@ #include namespace loot { - + class Game; /* Each Game object should store the config details specific to that game. @@ -78,7 +78,7 @@ namespace loot { bool Load(Game& game, const unsigned int language); //Handles update with load fallback. bool Update(Game& game, const unsigned int language); - + std::string GetRevision(const boost::filesystem::path& path); std::string GetDate(const boost::filesystem::path& path); @@ -96,7 +96,7 @@ namespace loot { Game(const unsigned int baseGameCode, const std::string& lootFolder = ""); Game& SetDetails(const std::string& name, const std::string& masterFile, - const std::string& repositoryURL, const std::string& repositoryBranch, + const std::string& repositoryURL, const std::string& repositoryBranch, const std::string& path, const std::string& registry); Game& SetPath(const std::string& path); //Used by API. Game& Init(); diff --git a/src/backend/git.cpp b/src/backend/git.cpp index 4e2af669..3adc3c1b 100644 --- a/src/backend/git.cpp +++ b/src/backend/git.cpp @@ -94,7 +94,6 @@ namespace loot { git_diff * diff; git_buf buf; - std::string ui_message; }; @@ -203,7 +202,8 @@ namespace loot { if (!fs::is_empty(repo_path)) { // Clear any read-only flags first. FixRepoPermissions(repo_path); - // Now, libgit2 doesn't support cloning into non-empty folders. Rename the folder + // Now, libgit2 doesn't support cloning into non-empty folders. Rename the folder + // temporarily, and move its contents back in afterwards, skipping any that then conflict. BOOST_LOG_TRIVIAL(trace) << "Repo path not empty, renaming folder."; // If the temp path already exists, it needs to be deleted. @@ -294,7 +294,6 @@ namespace loot { const git_oid * commit_id = git_object_id(git.obj); BOOST_LOG_TRIVIAL(trace) << "Creating the new branch."; - // Create a branch. git.call(git_commit_lookup(&git.commit, git.repo, commit_id)); git.call(git_branch_create(&git.ref, git.repo, repo_branch.c_str(), git.commit, 0, git.sig, NULL)); @@ -303,7 +302,6 @@ namespace loot { git.call(git_branch_set_upstream(git.ref, (string("origin/") + repo_branch).c_str())); BOOST_LOG_TRIVIAL(trace) << "Setting the upstream for the new branch."; - // Free tree and commit pointers. Reference pointer is still used below. git_object_free(git.obj); git_commit_free(git.commit); diff --git a/src/backend/metadata.cpp b/src/backend/metadata.cpp index 71bbf562..1a0a816f 100644 --- a/src/backend/metadata.cpp +++ b/src/backend/metadata.cpp @@ -460,7 +460,6 @@ namespace loot { p.Priority(0); p.SetPriorityExplicit(false); } - //Compare this plugin against the given plugin. set files = plugin.LoadAfter(); diff --git a/src/backend/metadata.h b/src/backend/metadata.h index c85acbe1..1bf040c2 100644 --- a/src/backend/metadata.h +++ b/src/backend/metadata.h @@ -172,7 +172,7 @@ namespace loot { //For 'enabled' and 'priority' metadata, use the given plugin's values, but if the 'priority' user value is zero, ignore it. void MergeMetadata(const Plugin& plugin); - //Returns the difference in metadata between the two plugins. + //Returns the difference in metadata between the two plugins. //For 'enabled', use the given plugin's value. //For 'priority', use the given plugin's value, unless it is equal to this plugin's value, in which case return 0. Plugin DiffMetadata(const Plugin& plugin) const; diff --git a/src/gui/app.cpp b/src/gui/app.cpp index 3dc8abae..b2b29b74 100644 --- a/src/gui/app.cpp +++ b/src/gui/app.cpp @@ -56,7 +56,7 @@ namespace loot { LootState g_app_state = LootState(); LootApp::LootApp() {} - + CefRefPtr LootApp::GetBrowserProcessHandler() { return this; } @@ -257,7 +257,8 @@ namespace loot { newGameFolders.insert(game.FolderName()); } - // Remove deleted games. As the current game is stored using its index, + // Remove deleted games. As the current game is stored using its index, + // removing an earlier game may invalidate it. for (auto it = _games.begin(); it != _games.end();) { if (newGameFolders.find(it->FolderName()) == newGameFolders.end()) { @@ -321,7 +322,7 @@ namespace loot { BOOST_LOG_TRIVIAL(error) << "Failed to save LOOT's settings. Error: " << e.what(); } } - + bool LootState::AreSettingsValid() { if (!_settings["language"]) { if (_settings["Language"]) { diff --git a/src/gui/app.h b/src/gui/app.h index 33cae986..5f595761 100644 --- a/src/gui/app.h +++ b/src/gui/app.h @@ -34,7 +34,7 @@ namespace loot { - class LootApp : public CefApp, + class LootApp : public CefApp, public CefBrowserProcessHandler, public CefRenderProcessHandler { public: @@ -66,7 +66,7 @@ namespace loot { public: LootState(); - // Init may fail with no + // Init may fail with no void Init(const std::string& cmdLineGame); const std::vector& InitErrors() const; diff --git a/src/gui/handler.cpp b/src/gui/handler.cpp index 759a2502..f236ec60 100644 --- a/src/gui/handler.cpp +++ b/src/gui/handler.cpp @@ -189,7 +189,6 @@ namespace loot { bool Handler::HandleComplexQuery(CefRefPtr browser, YAML::Node& request, CefRefPtr callback) { - const string requestName = request["name"].as(); if (requestName == "find") { @@ -254,7 +253,7 @@ namespace loot { } else if (requestName == "closeSettings") { BOOST_LOG_TRIVIAL(trace) << "Settings dialog closed and changes accepted, updating settings object."; - + // Update the game details and settings. g_app_state.UpdateSettings(request["args"][0]); // If the user has deleted a default game, we don't want to restore it now. @@ -733,7 +732,8 @@ namespace loot { } catch (loot::error &e) { if (e.code() == loot::error::ok) { - // There was a parsing error, but roll-back was successful, so the process + // There was a parsing error, but roll-back was successful, so the process + // should still complete. g_app_state.CurrentGame().masterlist.messages.push_back(Message(Message::error, e.what())); wasChanged = true; @@ -914,7 +914,6 @@ namespace loot { } YAML::Node Handler::GenerateDerivedMetadata(const std::string& pluginName) { - // Now rederive the displayed metadata from the masterlist and userlist. auto pluginIt = g_app_state.CurrentGame().plugins.find(boost::locale::to_lower(pluginName)); if (pluginIt != g_app_state.CurrentGame().plugins.end()) { @@ -939,7 +938,8 @@ namespace loot { } // The clipboard takes a Unicode (ie. UTF-16) string that it then owns and must not - // be destroyed by LOOT. Convert the string, then copy it into a new block of + // be destroyed by LOOT. Convert the string, then copy it into a new block of + // memory for the clipboard. wstring wtext = ToWinWide(text); wchar_t * wcstr = new wchar_t[wtext.length() + 1]; @@ -981,7 +981,7 @@ namespace loot { CefRefPtr LootHandler::GetLifeSpanHandler() { return this; } - + CefRefPtr LootHandler::GetLoadHandler() { return this; } @@ -1133,7 +1133,7 @@ namespace loot { << "

    Failed to load URL " << std::string(failedUrl) << " with error " << std::string(errorText) << " (" << errorCode << ").

    "; - + frame->LoadString(ss.str(), failedUrl); } diff --git a/src/gui/handler.h b/src/gui/handler.h index d4d72978..a3910cf6 100644 --- a/src/gui/handler.h +++ b/src/gui/handler.h @@ -62,7 +62,7 @@ namespace loot { void SortPlugins(CefRefPtr callback); // Handle queries with input arguments. - bool HandleComplexQuery(CefRefPtr browser, YAML::Node& request, + bool HandleComplexQuery(CefRefPtr browser, YAML::Node& request, CefRefPtr callback); void Find(CefRefPtr browser, const std::string& search); @@ -75,7 +75,7 @@ namespace loot { YAML::Node Handler::GenerateDerivedMetadata(const std::string& pluginName); YAML::Node Handler::GenerateDerivedMetadata(const Plugin& file, const Plugin& masterlist, const Plugin& userlist); - void CopyToClipboard(const std::string& text); + void CopyToClipboard(const std::string& text); private: IMPLEMENT_REFCOUNTING(Handler); }; @@ -129,9 +129,9 @@ namespace loot { return this; } - virtual bool OnBeforeBrowse(CefRefPtr< CefBrowser > browser, - CefRefPtr< CefFrame > frame, - CefRefPtr< CefRequest > request, + virtual bool OnBeforeBrowse(CefRefPtr< CefBrowser > browser, + CefRefPtr< CefFrame > frame, + CefRefPtr< CefRequest > request, bool is_redirect) OVERRIDE; // Request that all existing browser windows close. diff --git a/src/gui/main_win.cpp b/src/gui/main_win.cpp index 526509c0..75b4325f 100644 --- a/src/gui/main_win.cpp +++ b/src/gui/main_win.cpp @@ -51,7 +51,7 @@ CefSettings GetCefSettings() { // Set CEF logging. CefString(&cef_settings.log_file).FromString((g_path_local / "CEFDebugLog.txt").string()); - + // Enable remote debugging. cef_settings.remote_debugging_port = 8080; From 93a1a36be2aaa8dfe70489bc0be81de2e098093c Mon Sep 17 00:00:00 2001 From: WrinklyNinja Date: Wed, 27 Aug 2014 08:02:49 +0100 Subject: [PATCH 16/82] Fixed git buffer not being freed in parsing loop. --- src/backend/git.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/backend/git.cpp b/src/backend/git.cpp index 3adc3c1b..6eb58881 100644 --- a/src/backend/git.cpp +++ b/src/backend/git.cpp @@ -412,10 +412,12 @@ namespace loot { BOOST_LOG_TRIVIAL(trace) << "Freeing pointers."; git_reference_free(git.ref); git_object_free(git.obj); + git_buf_free(&git.buf); git_commit_free(git.commit); git.ref = nullptr; git.obj = nullptr; git.commit = nullptr; + git.buf = { 0 }; //Now try parsing the masterlist. BOOST_LOG_TRIVIAL(debug) << "Testing masterlist parsing."; From 40a7fb366265714020ecad30888cd60964545b4a Mon Sep 17 00:00:00 2001 From: WrinklyNinja Date: Wed, 27 Aug 2014 09:50:20 +0100 Subject: [PATCH 17/82] Added progress feedback for GetGameData(). Used by init, game change and on-focus refresh. --- src/gui/handler.cpp | 24 ++++++++++++++++++------ src/gui/handler.h | 7 +++++-- 2 files changed, 23 insertions(+), 8 deletions(-) diff --git a/src/gui/handler.cpp b/src/gui/handler.cpp index f236ec60..c8ca1f42 100644 --- a/src/gui/handler.cpp +++ b/src/gui/handler.cpp @@ -125,7 +125,7 @@ namespace loot { #ifdef _WIN32 SetWindowText(handle, ToWinWide("LOOT: " + g_app_state.CurrentGame().Name()).c_str()); #endif - return CefPostTask(TID_FILE, base::Bind(&Handler::GetGameData, base::Unretained(this), callback)); + return CefPostTask(TID_FILE, base::Bind(&Handler::GetGameData, base::Unretained(this), frame, callback)); } else if (request == "cancelFind") { browser->GetHost()->StopFinding(true); @@ -179,15 +179,17 @@ namespace loot { return true; } - return HandleComplexQuery(browser, req, callback); + return HandleComplexQuery(browser, frame, req, callback); } return false; } // Handle queries with input arguments. - bool Handler::HandleComplexQuery(CefRefPtr browser, YAML::Node& request, - CefRefPtr callback) { + bool Handler::HandleComplexQuery(CefRefPtr browser, + CefRefPtr frame, + YAML::Node& request, + CefRefPtr callback) { const string requestName = request["name"].as(); @@ -207,7 +209,7 @@ namespace loot { #ifdef _WIN32 SetWindowText(handle, ToWinWide("LOOT: " + g_app_state.CurrentGame().Name()).c_str()); #endif - CefPostTask(TID_FILE, base::Bind(&Handler::GetGameData, base::Unretained(this), callback)); + CefPostTask(TID_FILE, base::Bind(&Handler::GetGameData, base::Unretained(this), frame, callback)); } catch (loot::error &e) { BOOST_LOG_TRIVIAL(error) << "Failed to change game. Details: " << e.what(); @@ -547,7 +549,7 @@ namespace loot { return "[]"; } - void Handler::GetGameData(CefRefPtr callback) { + void Handler::GetGameData(CefRefPtr frame, CefRefPtr callback) { try { /* GetGameData() can be called for initialising the UI for a game for the first time in a session, or it can be called when changing to a game that has previously been @@ -558,6 +560,8 @@ namespace loot { BOOST_LOG_TRIVIAL(info) << "Getting data specific to LOOT's active game."; // Get masterlist revision info and parse if it exists. Also get plugin headers info and parse userlist if it exists. + SendProgressUpdate(frame, "Loading plugin headers..."); + bool isFirstLoad = g_app_state.CurrentGame().plugins.empty(); g_app_state.CurrentGame().LoadPlugins(true); @@ -575,6 +579,7 @@ namespace loot { if (isFirstLoad) { //Parse masterlist, don't update it. if (fs::exists(g_app_state.CurrentGame().MasterlistPath())) { + SendProgressUpdate(frame, "Parsing masterlist..."); BOOST_LOG_TRIVIAL(debug) << "Parsing masterlist."; try { g_app_state.CurrentGame().masterlist.MetadataList::Load(g_app_state.CurrentGame().MasterlistPath()); @@ -586,6 +591,7 @@ namespace loot { //Parse userlist. if (fs::exists(g_app_state.CurrentGame().UserlistPath())) { + SendProgressUpdate(frame, "Parsing userlist..."); BOOST_LOG_TRIVIAL(debug) << "Parsing userlist."; try { g_app_state.CurrentGame().userlist.Load(g_app_state.CurrentGame().UserlistPath()); @@ -612,6 +618,7 @@ namespace loot { } // Now store plugin data. + SendProgressUpdate(frame, "Merging and evaluating plugin metadata..."); for (const auto& plugin : installed) { /* Each plugin has members while hold its raw masterlist and userlist data for the editor, and also processed data for the main display. @@ -671,6 +678,7 @@ namespace loot { } if (isFirstLoad) { + SendProgressUpdate(frame, "Loading general messages..."); //Set language. unsigned int language; if (g_app_state.GetSettings()["language"]) @@ -955,6 +963,10 @@ namespace loot { #endif } + void Handler::SendProgressUpdate(CefRefPtr frame, const std::string& message) { + frame->ExecuteJavaScript("updateProgressDialog('" + message + "');", frame->GetURL(), 0); + } + // LootHandler methods //-------------------- diff --git a/src/gui/handler.h b/src/gui/handler.h index a3910cf6..df42678c 100644 --- a/src/gui/handler.h +++ b/src/gui/handler.h @@ -56,13 +56,15 @@ namespace loot { std::string GetLanguages(); std::string GetGameTypes(); std::string GetInstalledGames(); - void GetGameData(CefRefPtr callback); + void GetGameData(CefRefPtr frame, CefRefPtr callback); void UpdateMasterlist(CefRefPtr callback); std::string ClearAllMetadata(); void SortPlugins(CefRefPtr callback); // Handle queries with input arguments. - bool HandleComplexQuery(CefRefPtr browser, YAML::Node& request, + bool HandleComplexQuery(CefRefPtr browser, + CefRefPtr frame, + YAML::Node& request, CefRefPtr callback); void Find(CefRefPtr browser, const std::string& search); @@ -76,6 +78,7 @@ namespace loot { YAML::Node Handler::GenerateDerivedMetadata(const Plugin& file, const Plugin& masterlist, const Plugin& userlist); void CopyToClipboard(const std::string& text); + void SendProgressUpdate(CefRefPtr frame, const std::string& message); private: IMPLEMENT_REFCOUNTING(Handler); }; From aea3ba79f4b25708cbd589eabbf2676d978cabb2 Mon Sep 17 00:00:00 2001 From: WrinklyNinja Date: Wed, 27 Aug 2014 09:59:07 +0100 Subject: [PATCH 18/82] Fixed async update + sort closing progress early. --- resources/report/js/script.js | 89 ++++++++++++++++++----------------- 1 file changed, 46 insertions(+), 43 deletions(-) diff --git a/resources/report/js/script.js b/resources/report/js/script.js index 804932de..c541a18c 100644 --- a/resources/report/js/script.js +++ b/resources/report/js/script.js @@ -668,7 +668,7 @@ function openReadme(evt) { function updateMasterlist(evt) { updateProgressDialog('Updating masterlist...'); openProgressDialog(); - loot.query('updateMasterlist').then(JSON.parse).then(function(result){ + return loot.query('updateMasterlist').then(JSON.parse).then(function(result){ if (result == null) { closeProgressDialog(); return; @@ -772,49 +772,52 @@ function closeProgressDialog() { } } function sortPlugins(evt) { - if (loot.settings.updateMasterlist) { - updateMasterlist(evt); - } - updateProgressDialog('Sorting plugins...'); - openProgressDialog(); - loot.query('sortPlugins').then(JSON.parse).then(function(result){ - if (result) { - var loadOrder = []; - result.forEach(function(plugin){ - loadOrder.push(plugin.name); - for (var i = 0; i < loot.game.plugins.length; ++i) { - if (loot.game.plugins[i].name == plugin.name) { - loot.game.plugins[i].crc = plugin.crc; - loot.game.plugins[i].isDummy = plugin.isDummy; - break; - } - } - }); - - if (loot.settings.neverTellMeTheOdds) { - /* Array shuffler from */ - for(var j, x, i = loadOrder.length; i; j = Math.floor(Math.random() * i), x = loadOrder[--i], loadOrder[i] = loadOrder[j], loadOrder[j] = x); - } - - /* Record the previous order in case the user cancels sorting. */ - /* Start at 2 to skip summary and general messages. */ - var cards = document.getElementsByTagName('main')[0].getElementsByTagName('plugin-card'); - loot.newLoadOrder = loadOrder; - loot.lastLoadOrder = []; - for (var i = 0; i < cards.length; ++i) { - loot.lastLoadOrder.push(cards[i].getElementsByTagName('h1')[0].textContent); - } - /* Now update the UI for the new order. */ - sortUIElements(loadOrder); - - /* Now hide the masterlist update buttons, and display the accept and - cancel sort buttons. */ - hideElement(document.getElementById('updateMasterlistButton')); - hideElement(document.getElementById('sortButton')); - showElement(document.getElementById('applySortButton')); - showElement(document.getElementById('cancelSortButton')); - closeProgressDialog(); + Promise.all([function(){ + if (loot.settings.updateMasterlist) { + updateMasterlist(evt); } + }]).then(function(){ + updateProgressDialog('Sorting plugins...'); + openProgressDialog(); + loot.query('sortPlugins').then(JSON.parse).then(function(result){ + if (result) { + var loadOrder = []; + result.forEach(function(plugin){ + loadOrder.push(plugin.name); + for (var i = 0; i < loot.game.plugins.length; ++i) { + if (loot.game.plugins[i].name == plugin.name) { + loot.game.plugins[i].crc = plugin.crc; + loot.game.plugins[i].isDummy = plugin.isDummy; + break; + } + } + }); + + if (loot.settings.neverTellMeTheOdds) { + /* Array shuffler from */ + for(var j, x, i = loadOrder.length; i; j = Math.floor(Math.random() * i), x = loadOrder[--i], loadOrder[i] = loadOrder[j], loadOrder[j] = x); + } + + /* Record the previous order in case the user cancels sorting. */ + /* Start at 2 to skip summary and general messages. */ + var cards = document.getElementsByTagName('main')[0].getElementsByTagName('plugin-card'); + loot.newLoadOrder = loadOrder; + loot.lastLoadOrder = []; + for (var i = 0; i < cards.length; ++i) { + loot.lastLoadOrder.push(cards[i].getElementsByTagName('h1')[0].textContent); + } + /* Now update the UI for the new order. */ + sortUIElements(loadOrder); + + /* Now hide the masterlist update buttons, and display the accept and + cancel sort buttons. */ + hideElement(document.getElementById('updateMasterlistButton')); + hideElement(document.getElementById('sortButton')); + showElement(document.getElementById('applySortButton')); + showElement(document.getElementById('cancelSortButton')); + closeProgressDialog(); + } + }).catch(processCefError); }).catch(processCefError); } function applySort(evt) { From cbb950faefa2cc48f70643971ccc1038df28258d Mon Sep 17 00:00:00 2001 From: WrinklyNinja Date: Wed, 27 Aug 2014 14:13:56 +0100 Subject: [PATCH 19/82] Fixed broken message dialog init. --- resources/report/js/custom.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/report/js/custom.js b/resources/report/js/custom.js index 06b9cd2b..81bc1a45 100644 --- a/resources/report/js/custom.js +++ b/resources/report/js/custom.js @@ -702,7 +702,7 @@ var messageDialogProto = Object.create(HTMLDialogElement.prototype, { if (type == 'error' || type == 'info') { this.getElementsByClassName('accept')[0].textContent = 'OK'; - this.getElementsByClassName('cancel')[0].style.display = 'hidden'; + this.getElementsByClassName('cancel')[0].classList.toggle('hidden', true); } HTMLDialogElement.prototype.showModal.call(this); From 21e4bc84ee8dbe683b6a6d4ffa4e73d032bdfdec Mon Sep 17 00:00:00 2001 From: WrinklyNinja Date: Wed, 27 Aug 2014 17:09:05 +0100 Subject: [PATCH 20/82] Updated FontAwesome to 4.2.0. --- resources/report/css/font-awesome.min.css | 4 ++-- .../report/fonts/fontawesome-webfont.woff | Bin 83760 -> 65452 bytes 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/resources/report/css/font-awesome.min.css b/resources/report/css/font-awesome.min.css index 3d920fc8..ec53d4d6 100644 --- a/resources/report/css/font-awesome.min.css +++ b/resources/report/css/font-awesome.min.css @@ -1,4 +1,4 @@ /*! - * Font Awesome 4.1.0 by @davegandy - http://fontawesome.io - @fontawesome + * Font Awesome 4.2.0 by @davegandy - http://fontawesome.io - @fontawesome * License - http://fontawesome.io/license (Font: SIL OFL 1.1, CSS: MIT License) - */@font-face{font-family:'FontAwesome';src:url('../fonts/fontawesome-webfont.eot?v=4.1.0');src:url('../fonts/fontawesome-webfont.eot?#iefix&v=4.1.0') format('embedded-opentype'),url('../fonts/fontawesome-webfont.woff?v=4.1.0') format('woff'),url('../fonts/fontawesome-webfont.ttf?v=4.1.0') format('truetype'),url('../fonts/fontawesome-webfont.svg?v=4.1.0#fontawesomeregular') format('svg');font-weight:normal;font-style:normal}.fa{display:inline-block;font-family:FontAwesome;font-style:normal;font-weight:normal;line-height:1;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.fa-lg{font-size:1.33333333em;line-height:.75em;vertical-align:-15%}.fa-2x{font-size:2em}.fa-3x{font-size:3em}.fa-4x{font-size:4em}.fa-5x{font-size:5em}.fa-fw{width:1.28571429em;text-align:center}.fa-ul{padding-left:0;margin-left:2.14285714em;list-style-type:none}.fa-ul>li{position:relative}.fa-li{position:absolute;left:-2.14285714em;width:2.14285714em;top:.14285714em;text-align:center}.fa-li.fa-lg{left:-1.85714286em}.fa-border{padding:.2em .25em .15em;border:solid .08em #eee;border-radius:.1em}.pull-right{float:right}.pull-left{float:left}.fa.pull-left{margin-right:.3em}.fa.pull-right{margin-left:.3em}.fa-spin{-webkit-animation:spin 2s infinite linear;-moz-animation:spin 2s infinite linear;-o-animation:spin 2s infinite linear;animation:spin 2s infinite linear}@-moz-keyframes spin{0%{-moz-transform:rotate(0deg)}100%{-moz-transform:rotate(359deg)}}@-webkit-keyframes spin{0%{-webkit-transform:rotate(0deg)}100%{-webkit-transform:rotate(359deg)}}@-o-keyframes spin{0%{-o-transform:rotate(0deg)}100%{-o-transform:rotate(359deg)}}@keyframes spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}100%{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}.fa-rotate-90{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=1);-webkit-transform:rotate(90deg);-moz-transform:rotate(90deg);-ms-transform:rotate(90deg);-o-transform:rotate(90deg);transform:rotate(90deg)}.fa-rotate-180{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=2);-webkit-transform:rotate(180deg);-moz-transform:rotate(180deg);-ms-transform:rotate(180deg);-o-transform:rotate(180deg);transform:rotate(180deg)}.fa-rotate-270{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=3);-webkit-transform:rotate(270deg);-moz-transform:rotate(270deg);-ms-transform:rotate(270deg);-o-transform:rotate(270deg);transform:rotate(270deg)}.fa-flip-horizontal{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=0, mirror=1);-webkit-transform:scale(-1, 1);-moz-transform:scale(-1, 1);-ms-transform:scale(-1, 1);-o-transform:scale(-1, 1);transform:scale(-1, 1)}.fa-flip-vertical{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=2, mirror=1);-webkit-transform:scale(1, -1);-moz-transform:scale(1, -1);-ms-transform:scale(1, -1);-o-transform:scale(1, -1);transform:scale(1, -1)}.fa-stack{position:relative;display:inline-block;width:2em;height:2em;line-height:2em;vertical-align:middle}.fa-stack-1x,.fa-stack-2x{position:absolute;left:0;width:100%;text-align:center}.fa-stack-1x{line-height:inherit}.fa-stack-2x{font-size:2em}.fa-inverse{color:#fff}.fa-glass:before{content:"\f000"}.fa-music:before{content:"\f001"}.fa-search:before{content:"\f002"}.fa-envelope-o:before{content:"\f003"}.fa-heart:before{content:"\f004"}.fa-star:before{content:"\f005"}.fa-star-o:before{content:"\f006"}.fa-user:before{content:"\f007"}.fa-film:before{content:"\f008"}.fa-th-large:before{content:"\f009"}.fa-th:before{content:"\f00a"}.fa-th-list:before{content:"\f00b"}.fa-check:before{content:"\f00c"}.fa-times:before{content:"\f00d"}.fa-search-plus:before{content:"\f00e"}.fa-search-minus:before{content:"\f010"}.fa-power-off:before{content:"\f011"}.fa-signal:before{content:"\f012"}.fa-gear:before,.fa-cog:before{content:"\f013"}.fa-trash-o:before{content:"\f014"}.fa-home:before{content:"\f015"}.fa-file-o:before{content:"\f016"}.fa-clock-o:before{content:"\f017"}.fa-road:before{content:"\f018"}.fa-download:before{content:"\f019"}.fa-arrow-circle-o-down:before{content:"\f01a"}.fa-arrow-circle-o-up:before{content:"\f01b"}.fa-inbox:before{content:"\f01c"}.fa-play-circle-o:before{content:"\f01d"}.fa-rotate-right:before,.fa-repeat:before{content:"\f01e"}.fa-refresh:before{content:"\f021"}.fa-list-alt:before{content:"\f022"}.fa-lock:before{content:"\f023"}.fa-flag:before{content:"\f024"}.fa-headphones:before{content:"\f025"}.fa-volume-off:before{content:"\f026"}.fa-volume-down:before{content:"\f027"}.fa-volume-up:before{content:"\f028"}.fa-qrcode:before{content:"\f029"}.fa-barcode:before{content:"\f02a"}.fa-tag:before{content:"\f02b"}.fa-tags:before{content:"\f02c"}.fa-book:before{content:"\f02d"}.fa-bookmark:before{content:"\f02e"}.fa-print:before{content:"\f02f"}.fa-camera:before{content:"\f030"}.fa-font:before{content:"\f031"}.fa-bold:before{content:"\f032"}.fa-italic:before{content:"\f033"}.fa-text-height:before{content:"\f034"}.fa-text-width:before{content:"\f035"}.fa-align-left:before{content:"\f036"}.fa-align-center:before{content:"\f037"}.fa-align-right:before{content:"\f038"}.fa-align-justify:before{content:"\f039"}.fa-list:before{content:"\f03a"}.fa-dedent:before,.fa-outdent:before{content:"\f03b"}.fa-indent:before{content:"\f03c"}.fa-video-camera:before{content:"\f03d"}.fa-photo:before,.fa-image:before,.fa-picture-o:before{content:"\f03e"}.fa-pencil:before{content:"\f040"}.fa-map-marker:before{content:"\f041"}.fa-adjust:before{content:"\f042"}.fa-tint:before{content:"\f043"}.fa-edit:before,.fa-pencil-square-o:before{content:"\f044"}.fa-share-square-o:before{content:"\f045"}.fa-check-square-o:before{content:"\f046"}.fa-arrows:before{content:"\f047"}.fa-step-backward:before{content:"\f048"}.fa-fast-backward:before{content:"\f049"}.fa-backward:before{content:"\f04a"}.fa-play:before{content:"\f04b"}.fa-pause:before{content:"\f04c"}.fa-stop:before{content:"\f04d"}.fa-forward:before{content:"\f04e"}.fa-fast-forward:before{content:"\f050"}.fa-step-forward:before{content:"\f051"}.fa-eject:before{content:"\f052"}.fa-chevron-left:before{content:"\f053"}.fa-chevron-right:before{content:"\f054"}.fa-plus-circle:before{content:"\f055"}.fa-minus-circle:before{content:"\f056"}.fa-times-circle:before{content:"\f057"}.fa-check-circle:before{content:"\f058"}.fa-question-circle:before{content:"\f059"}.fa-info-circle:before{content:"\f05a"}.fa-crosshairs:before{content:"\f05b"}.fa-times-circle-o:before{content:"\f05c"}.fa-check-circle-o:before{content:"\f05d"}.fa-ban:before{content:"\f05e"}.fa-arrow-left:before{content:"\f060"}.fa-arrow-right:before{content:"\f061"}.fa-arrow-up:before{content:"\f062"}.fa-arrow-down:before{content:"\f063"}.fa-mail-forward:before,.fa-share:before{content:"\f064"}.fa-expand:before{content:"\f065"}.fa-compress:before{content:"\f066"}.fa-plus:before{content:"\f067"}.fa-minus:before{content:"\f068"}.fa-asterisk:before{content:"\f069"}.fa-exclamation-circle:before{content:"\f06a"}.fa-gift:before{content:"\f06b"}.fa-leaf:before{content:"\f06c"}.fa-fire:before{content:"\f06d"}.fa-eye:before{content:"\f06e"}.fa-eye-slash:before{content:"\f070"}.fa-warning:before,.fa-exclamation-triangle:before{content:"\f071"}.fa-plane:before{content:"\f072"}.fa-calendar:before{content:"\f073"}.fa-random:before{content:"\f074"}.fa-comment:before{content:"\f075"}.fa-magnet:before{content:"\f076"}.fa-chevron-up:before{content:"\f077"}.fa-chevron-down:before{content:"\f078"}.fa-retweet:before{content:"\f079"}.fa-shopping-cart:before{content:"\f07a"}.fa-folder:before{content:"\f07b"}.fa-folder-open:before{content:"\f07c"}.fa-arrows-v:before{content:"\f07d"}.fa-arrows-h:before{content:"\f07e"}.fa-bar-chart-o:before{content:"\f080"}.fa-twitter-square:before{content:"\f081"}.fa-facebook-square:before{content:"\f082"}.fa-camera-retro:before{content:"\f083"}.fa-key:before{content:"\f084"}.fa-gears:before,.fa-cogs:before{content:"\f085"}.fa-comments:before{content:"\f086"}.fa-thumbs-o-up:before{content:"\f087"}.fa-thumbs-o-down:before{content:"\f088"}.fa-star-half:before{content:"\f089"}.fa-heart-o:before{content:"\f08a"}.fa-sign-out:before{content:"\f08b"}.fa-linkedin-square:before{content:"\f08c"}.fa-thumb-tack:before{content:"\f08d"}.fa-external-link:before{content:"\f08e"}.fa-sign-in:before{content:"\f090"}.fa-trophy:before{content:"\f091"}.fa-github-square:before{content:"\f092"}.fa-upload:before{content:"\f093"}.fa-lemon-o:before{content:"\f094"}.fa-phone:before{content:"\f095"}.fa-square-o:before{content:"\f096"}.fa-bookmark-o:before{content:"\f097"}.fa-phone-square:before{content:"\f098"}.fa-twitter:before{content:"\f099"}.fa-facebook:before{content:"\f09a"}.fa-github:before{content:"\f09b"}.fa-unlock:before{content:"\f09c"}.fa-credit-card:before{content:"\f09d"}.fa-rss:before{content:"\f09e"}.fa-hdd-o:before{content:"\f0a0"}.fa-bullhorn:before{content:"\f0a1"}.fa-bell:before{content:"\f0f3"}.fa-certificate:before{content:"\f0a3"}.fa-hand-o-right:before{content:"\f0a4"}.fa-hand-o-left:before{content:"\f0a5"}.fa-hand-o-up:before{content:"\f0a6"}.fa-hand-o-down:before{content:"\f0a7"}.fa-arrow-circle-left:before{content:"\f0a8"}.fa-arrow-circle-right:before{content:"\f0a9"}.fa-arrow-circle-up:before{content:"\f0aa"}.fa-arrow-circle-down:before{content:"\f0ab"}.fa-globe:before{content:"\f0ac"}.fa-wrench:before{content:"\f0ad"}.fa-tasks:before{content:"\f0ae"}.fa-filter:before{content:"\f0b0"}.fa-briefcase:before{content:"\f0b1"}.fa-arrows-alt:before{content:"\f0b2"}.fa-group:before,.fa-users:before{content:"\f0c0"}.fa-chain:before,.fa-link:before{content:"\f0c1"}.fa-cloud:before{content:"\f0c2"}.fa-flask:before{content:"\f0c3"}.fa-cut:before,.fa-scissors:before{content:"\f0c4"}.fa-copy:before,.fa-files-o:before{content:"\f0c5"}.fa-paperclip:before{content:"\f0c6"}.fa-save:before,.fa-floppy-o:before{content:"\f0c7"}.fa-square:before{content:"\f0c8"}.fa-navicon:before,.fa-reorder:before,.fa-bars:before{content:"\f0c9"}.fa-list-ul:before{content:"\f0ca"}.fa-list-ol:before{content:"\f0cb"}.fa-strikethrough:before{content:"\f0cc"}.fa-underline:before{content:"\f0cd"}.fa-table:before{content:"\f0ce"}.fa-magic:before{content:"\f0d0"}.fa-truck:before{content:"\f0d1"}.fa-pinterest:before{content:"\f0d2"}.fa-pinterest-square:before{content:"\f0d3"}.fa-google-plus-square:before{content:"\f0d4"}.fa-google-plus:before{content:"\f0d5"}.fa-money:before{content:"\f0d6"}.fa-caret-down:before{content:"\f0d7"}.fa-caret-up:before{content:"\f0d8"}.fa-caret-left:before{content:"\f0d9"}.fa-caret-right:before{content:"\f0da"}.fa-columns:before{content:"\f0db"}.fa-unsorted:before,.fa-sort:before{content:"\f0dc"}.fa-sort-down:before,.fa-sort-desc:before{content:"\f0dd"}.fa-sort-up:before,.fa-sort-asc:before{content:"\f0de"}.fa-envelope:before{content:"\f0e0"}.fa-linkedin:before{content:"\f0e1"}.fa-rotate-left:before,.fa-undo:before{content:"\f0e2"}.fa-legal:before,.fa-gavel:before{content:"\f0e3"}.fa-dashboard:before,.fa-tachometer:before{content:"\f0e4"}.fa-comment-o:before{content:"\f0e5"}.fa-comments-o:before{content:"\f0e6"}.fa-flash:before,.fa-bolt:before{content:"\f0e7"}.fa-sitemap:before{content:"\f0e8"}.fa-umbrella:before{content:"\f0e9"}.fa-paste:before,.fa-clipboard:before{content:"\f0ea"}.fa-lightbulb-o:before{content:"\f0eb"}.fa-exchange:before{content:"\f0ec"}.fa-cloud-download:before{content:"\f0ed"}.fa-cloud-upload:before{content:"\f0ee"}.fa-user-md:before{content:"\f0f0"}.fa-stethoscope:before{content:"\f0f1"}.fa-suitcase:before{content:"\f0f2"}.fa-bell-o:before{content:"\f0a2"}.fa-coffee:before{content:"\f0f4"}.fa-cutlery:before{content:"\f0f5"}.fa-file-text-o:before{content:"\f0f6"}.fa-building-o:before{content:"\f0f7"}.fa-hospital-o:before{content:"\f0f8"}.fa-ambulance:before{content:"\f0f9"}.fa-medkit:before{content:"\f0fa"}.fa-fighter-jet:before{content:"\f0fb"}.fa-beer:before{content:"\f0fc"}.fa-h-square:before{content:"\f0fd"}.fa-plus-square:before{content:"\f0fe"}.fa-angle-double-left:before{content:"\f100"}.fa-angle-double-right:before{content:"\f101"}.fa-angle-double-up:before{content:"\f102"}.fa-angle-double-down:before{content:"\f103"}.fa-angle-left:before{content:"\f104"}.fa-angle-right:before{content:"\f105"}.fa-angle-up:before{content:"\f106"}.fa-angle-down:before{content:"\f107"}.fa-desktop:before{content:"\f108"}.fa-laptop:before{content:"\f109"}.fa-tablet:before{content:"\f10a"}.fa-mobile-phone:before,.fa-mobile:before{content:"\f10b"}.fa-circle-o:before{content:"\f10c"}.fa-quote-left:before{content:"\f10d"}.fa-quote-right:before{content:"\f10e"}.fa-spinner:before{content:"\f110"}.fa-circle:before{content:"\f111"}.fa-mail-reply:before,.fa-reply:before{content:"\f112"}.fa-github-alt:before{content:"\f113"}.fa-folder-o:before{content:"\f114"}.fa-folder-open-o:before{content:"\f115"}.fa-smile-o:before{content:"\f118"}.fa-frown-o:before{content:"\f119"}.fa-meh-o:before{content:"\f11a"}.fa-gamepad:before{content:"\f11b"}.fa-keyboard-o:before{content:"\f11c"}.fa-flag-o:before{content:"\f11d"}.fa-flag-checkered:before{content:"\f11e"}.fa-terminal:before{content:"\f120"}.fa-code:before{content:"\f121"}.fa-mail-reply-all:before,.fa-reply-all:before{content:"\f122"}.fa-star-half-empty:before,.fa-star-half-full:before,.fa-star-half-o:before{content:"\f123"}.fa-location-arrow:before{content:"\f124"}.fa-crop:before{content:"\f125"}.fa-code-fork:before{content:"\f126"}.fa-unlink:before,.fa-chain-broken:before{content:"\f127"}.fa-question:before{content:"\f128"}.fa-info:before{content:"\f129"}.fa-exclamation:before{content:"\f12a"}.fa-superscript:before{content:"\f12b"}.fa-subscript:before{content:"\f12c"}.fa-eraser:before{content:"\f12d"}.fa-puzzle-piece:before{content:"\f12e"}.fa-microphone:before{content:"\f130"}.fa-microphone-slash:before{content:"\f131"}.fa-shield:before{content:"\f132"}.fa-calendar-o:before{content:"\f133"}.fa-fire-extinguisher:before{content:"\f134"}.fa-rocket:before{content:"\f135"}.fa-maxcdn:before{content:"\f136"}.fa-chevron-circle-left:before{content:"\f137"}.fa-chevron-circle-right:before{content:"\f138"}.fa-chevron-circle-up:before{content:"\f139"}.fa-chevron-circle-down:before{content:"\f13a"}.fa-html5:before{content:"\f13b"}.fa-css3:before{content:"\f13c"}.fa-anchor:before{content:"\f13d"}.fa-unlock-alt:before{content:"\f13e"}.fa-bullseye:before{content:"\f140"}.fa-ellipsis-h:before{content:"\f141"}.fa-ellipsis-v:before{content:"\f142"}.fa-rss-square:before{content:"\f143"}.fa-play-circle:before{content:"\f144"}.fa-ticket:before{content:"\f145"}.fa-minus-square:before{content:"\f146"}.fa-minus-square-o:before{content:"\f147"}.fa-level-up:before{content:"\f148"}.fa-level-down:before{content:"\f149"}.fa-check-square:before{content:"\f14a"}.fa-pencil-square:before{content:"\f14b"}.fa-external-link-square:before{content:"\f14c"}.fa-share-square:before{content:"\f14d"}.fa-compass:before{content:"\f14e"}.fa-toggle-down:before,.fa-caret-square-o-down:before{content:"\f150"}.fa-toggle-up:before,.fa-caret-square-o-up:before{content:"\f151"}.fa-toggle-right:before,.fa-caret-square-o-right:before{content:"\f152"}.fa-euro:before,.fa-eur:before{content:"\f153"}.fa-gbp:before{content:"\f154"}.fa-dollar:before,.fa-usd:before{content:"\f155"}.fa-rupee:before,.fa-inr:before{content:"\f156"}.fa-cny:before,.fa-rmb:before,.fa-yen:before,.fa-jpy:before{content:"\f157"}.fa-ruble:before,.fa-rouble:before,.fa-rub:before{content:"\f158"}.fa-won:before,.fa-krw:before{content:"\f159"}.fa-bitcoin:before,.fa-btc:before{content:"\f15a"}.fa-file:before{content:"\f15b"}.fa-file-text:before{content:"\f15c"}.fa-sort-alpha-asc:before{content:"\f15d"}.fa-sort-alpha-desc:before{content:"\f15e"}.fa-sort-amount-asc:before{content:"\f160"}.fa-sort-amount-desc:before{content:"\f161"}.fa-sort-numeric-asc:before{content:"\f162"}.fa-sort-numeric-desc:before{content:"\f163"}.fa-thumbs-up:before{content:"\f164"}.fa-thumbs-down:before{content:"\f165"}.fa-youtube-square:before{content:"\f166"}.fa-youtube:before{content:"\f167"}.fa-xing:before{content:"\f168"}.fa-xing-square:before{content:"\f169"}.fa-youtube-play:before{content:"\f16a"}.fa-dropbox:before{content:"\f16b"}.fa-stack-overflow:before{content:"\f16c"}.fa-instagram:before{content:"\f16d"}.fa-flickr:before{content:"\f16e"}.fa-adn:before{content:"\f170"}.fa-bitbucket:before{content:"\f171"}.fa-bitbucket-square:before{content:"\f172"}.fa-tumblr:before{content:"\f173"}.fa-tumblr-square:before{content:"\f174"}.fa-long-arrow-down:before{content:"\f175"}.fa-long-arrow-up:before{content:"\f176"}.fa-long-arrow-left:before{content:"\f177"}.fa-long-arrow-right:before{content:"\f178"}.fa-apple:before{content:"\f179"}.fa-windows:before{content:"\f17a"}.fa-android:before{content:"\f17b"}.fa-linux:before{content:"\f17c"}.fa-dribbble:before{content:"\f17d"}.fa-skype:before{content:"\f17e"}.fa-foursquare:before{content:"\f180"}.fa-trello:before{content:"\f181"}.fa-female:before{content:"\f182"}.fa-male:before{content:"\f183"}.fa-gittip:before{content:"\f184"}.fa-sun-o:before{content:"\f185"}.fa-moon-o:before{content:"\f186"}.fa-archive:before{content:"\f187"}.fa-bug:before{content:"\f188"}.fa-vk:before{content:"\f189"}.fa-weibo:before{content:"\f18a"}.fa-renren:before{content:"\f18b"}.fa-pagelines:before{content:"\f18c"}.fa-stack-exchange:before{content:"\f18d"}.fa-arrow-circle-o-right:before{content:"\f18e"}.fa-arrow-circle-o-left:before{content:"\f190"}.fa-toggle-left:before,.fa-caret-square-o-left:before{content:"\f191"}.fa-dot-circle-o:before{content:"\f192"}.fa-wheelchair:before{content:"\f193"}.fa-vimeo-square:before{content:"\f194"}.fa-turkish-lira:before,.fa-try:before{content:"\f195"}.fa-plus-square-o:before{content:"\f196"}.fa-space-shuttle:before{content:"\f197"}.fa-slack:before{content:"\f198"}.fa-envelope-square:before{content:"\f199"}.fa-wordpress:before{content:"\f19a"}.fa-openid:before{content:"\f19b"}.fa-institution:before,.fa-bank:before,.fa-university:before{content:"\f19c"}.fa-mortar-board:before,.fa-graduation-cap:before{content:"\f19d"}.fa-yahoo:before{content:"\f19e"}.fa-google:before{content:"\f1a0"}.fa-reddit:before{content:"\f1a1"}.fa-reddit-square:before{content:"\f1a2"}.fa-stumbleupon-circle:before{content:"\f1a3"}.fa-stumbleupon:before{content:"\f1a4"}.fa-delicious:before{content:"\f1a5"}.fa-digg:before{content:"\f1a6"}.fa-pied-piper-square:before,.fa-pied-piper:before{content:"\f1a7"}.fa-pied-piper-alt:before{content:"\f1a8"}.fa-drupal:before{content:"\f1a9"}.fa-joomla:before{content:"\f1aa"}.fa-language:before{content:"\f1ab"}.fa-fax:before{content:"\f1ac"}.fa-building:before{content:"\f1ad"}.fa-child:before{content:"\f1ae"}.fa-paw:before{content:"\f1b0"}.fa-spoon:before{content:"\f1b1"}.fa-cube:before{content:"\f1b2"}.fa-cubes:before{content:"\f1b3"}.fa-behance:before{content:"\f1b4"}.fa-behance-square:before{content:"\f1b5"}.fa-steam:before{content:"\f1b6"}.fa-steam-square:before{content:"\f1b7"}.fa-recycle:before{content:"\f1b8"}.fa-automobile:before,.fa-car:before{content:"\f1b9"}.fa-cab:before,.fa-taxi:before{content:"\f1ba"}.fa-tree:before{content:"\f1bb"}.fa-spotify:before{content:"\f1bc"}.fa-deviantart:before{content:"\f1bd"}.fa-soundcloud:before{content:"\f1be"}.fa-database:before{content:"\f1c0"}.fa-file-pdf-o:before{content:"\f1c1"}.fa-file-word-o:before{content:"\f1c2"}.fa-file-excel-o:before{content:"\f1c3"}.fa-file-powerpoint-o:before{content:"\f1c4"}.fa-file-photo-o:before,.fa-file-picture-o:before,.fa-file-image-o:before{content:"\f1c5"}.fa-file-zip-o:before,.fa-file-archive-o:before{content:"\f1c6"}.fa-file-sound-o:before,.fa-file-audio-o:before{content:"\f1c7"}.fa-file-movie-o:before,.fa-file-video-o:before{content:"\f1c8"}.fa-file-code-o:before{content:"\f1c9"}.fa-vine:before{content:"\f1ca"}.fa-codepen:before{content:"\f1cb"}.fa-jsfiddle:before{content:"\f1cc"}.fa-life-bouy:before,.fa-life-saver:before,.fa-support:before,.fa-life-ring:before{content:"\f1cd"}.fa-circle-o-notch:before{content:"\f1ce"}.fa-ra:before,.fa-rebel:before{content:"\f1d0"}.fa-ge:before,.fa-empire:before{content:"\f1d1"}.fa-git-square:before{content:"\f1d2"}.fa-git:before{content:"\f1d3"}.fa-hacker-news:before{content:"\f1d4"}.fa-tencent-weibo:before{content:"\f1d5"}.fa-qq:before{content:"\f1d6"}.fa-wechat:before,.fa-weixin:before{content:"\f1d7"}.fa-send:before,.fa-paper-plane:before{content:"\f1d8"}.fa-send-o:before,.fa-paper-plane-o:before{content:"\f1d9"}.fa-history:before{content:"\f1da"}.fa-circle-thin:before{content:"\f1db"}.fa-header:before{content:"\f1dc"}.fa-paragraph:before{content:"\f1dd"}.fa-sliders:before{content:"\f1de"}.fa-share-alt:before{content:"\f1e0"}.fa-share-alt-square:before{content:"\f1e1"}.fa-bomb:before{content:"\f1e2"} \ No newline at end of file + */@font-face{font-family:'FontAwesome';src:url('../fonts/fontawesome-webfont.eot?v=4.2.0');src:url('../fonts/fontawesome-webfont.eot?#iefix&v=4.2.0') format('embedded-opentype'),url('../fonts/fontawesome-webfont.woff?v=4.2.0') format('woff'),url('../fonts/fontawesome-webfont.ttf?v=4.2.0') format('truetype'),url('../fonts/fontawesome-webfont.svg?v=4.2.0#fontawesomeregular') format('svg');font-weight:normal;font-style:normal}.fa{display:inline-block;font:normal normal normal 14px/1 FontAwesome;font-size:inherit;text-rendering:auto;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.fa-lg{font-size:1.33333333em;line-height:.75em;vertical-align:-15%}.fa-2x{font-size:2em}.fa-3x{font-size:3em}.fa-4x{font-size:4em}.fa-5x{font-size:5em}.fa-fw{width:1.28571429em;text-align:center}.fa-ul{padding-left:0;margin-left:2.14285714em;list-style-type:none}.fa-ul>li{position:relative}.fa-li{position:absolute;left:-2.14285714em;width:2.14285714em;top:.14285714em;text-align:center}.fa-li.fa-lg{left:-1.85714286em}.fa-border{padding:.2em .25em .15em;border:solid .08em #eee;border-radius:.1em}.pull-right{float:right}.pull-left{float:left}.fa.pull-left{margin-right:.3em}.fa.pull-right{margin-left:.3em}.fa-spin{-webkit-animation:fa-spin 2s infinite linear;animation:fa-spin 2s infinite linear}@-webkit-keyframes fa-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}100%{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}@keyframes fa-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}100%{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}.fa-rotate-90{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=1);-webkit-transform:rotate(90deg);-ms-transform:rotate(90deg);transform:rotate(90deg)}.fa-rotate-180{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=2);-webkit-transform:rotate(180deg);-ms-transform:rotate(180deg);transform:rotate(180deg)}.fa-rotate-270{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=3);-webkit-transform:rotate(270deg);-ms-transform:rotate(270deg);transform:rotate(270deg)}.fa-flip-horizontal{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=0, mirror=1);-webkit-transform:scale(-1, 1);-ms-transform:scale(-1, 1);transform:scale(-1, 1)}.fa-flip-vertical{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=2, mirror=1);-webkit-transform:scale(1, -1);-ms-transform:scale(1, -1);transform:scale(1, -1)}:root .fa-rotate-90,:root .fa-rotate-180,:root .fa-rotate-270,:root .fa-flip-horizontal,:root .fa-flip-vertical{filter:none}.fa-stack{position:relative;display:inline-block;width:2em;height:2em;line-height:2em;vertical-align:middle}.fa-stack-1x,.fa-stack-2x{position:absolute;left:0;width:100%;text-align:center}.fa-stack-1x{line-height:inherit}.fa-stack-2x{font-size:2em}.fa-inverse{color:#fff}.fa-glass:before{content:"\f000"}.fa-music:before{content:"\f001"}.fa-search:before{content:"\f002"}.fa-envelope-o:before{content:"\f003"}.fa-heart:before{content:"\f004"}.fa-star:before{content:"\f005"}.fa-star-o:before{content:"\f006"}.fa-user:before{content:"\f007"}.fa-film:before{content:"\f008"}.fa-th-large:before{content:"\f009"}.fa-th:before{content:"\f00a"}.fa-th-list:before{content:"\f00b"}.fa-check:before{content:"\f00c"}.fa-remove:before,.fa-close:before,.fa-times:before{content:"\f00d"}.fa-search-plus:before{content:"\f00e"}.fa-search-minus:before{content:"\f010"}.fa-power-off:before{content:"\f011"}.fa-signal:before{content:"\f012"}.fa-gear:before,.fa-cog:before{content:"\f013"}.fa-trash-o:before{content:"\f014"}.fa-home:before{content:"\f015"}.fa-file-o:before{content:"\f016"}.fa-clock-o:before{content:"\f017"}.fa-road:before{content:"\f018"}.fa-download:before{content:"\f019"}.fa-arrow-circle-o-down:before{content:"\f01a"}.fa-arrow-circle-o-up:before{content:"\f01b"}.fa-inbox:before{content:"\f01c"}.fa-play-circle-o:before{content:"\f01d"}.fa-rotate-right:before,.fa-repeat:before{content:"\f01e"}.fa-refresh:before{content:"\f021"}.fa-list-alt:before{content:"\f022"}.fa-lock:before{content:"\f023"}.fa-flag:before{content:"\f024"}.fa-headphones:before{content:"\f025"}.fa-volume-off:before{content:"\f026"}.fa-volume-down:before{content:"\f027"}.fa-volume-up:before{content:"\f028"}.fa-qrcode:before{content:"\f029"}.fa-barcode:before{content:"\f02a"}.fa-tag:before{content:"\f02b"}.fa-tags:before{content:"\f02c"}.fa-book:before{content:"\f02d"}.fa-bookmark:before{content:"\f02e"}.fa-print:before{content:"\f02f"}.fa-camera:before{content:"\f030"}.fa-font:before{content:"\f031"}.fa-bold:before{content:"\f032"}.fa-italic:before{content:"\f033"}.fa-text-height:before{content:"\f034"}.fa-text-width:before{content:"\f035"}.fa-align-left:before{content:"\f036"}.fa-align-center:before{content:"\f037"}.fa-align-right:before{content:"\f038"}.fa-align-justify:before{content:"\f039"}.fa-list:before{content:"\f03a"}.fa-dedent:before,.fa-outdent:before{content:"\f03b"}.fa-indent:before{content:"\f03c"}.fa-video-camera:before{content:"\f03d"}.fa-photo:before,.fa-image:before,.fa-picture-o:before{content:"\f03e"}.fa-pencil:before{content:"\f040"}.fa-map-marker:before{content:"\f041"}.fa-adjust:before{content:"\f042"}.fa-tint:before{content:"\f043"}.fa-edit:before,.fa-pencil-square-o:before{content:"\f044"}.fa-share-square-o:before{content:"\f045"}.fa-check-square-o:before{content:"\f046"}.fa-arrows:before{content:"\f047"}.fa-step-backward:before{content:"\f048"}.fa-fast-backward:before{content:"\f049"}.fa-backward:before{content:"\f04a"}.fa-play:before{content:"\f04b"}.fa-pause:before{content:"\f04c"}.fa-stop:before{content:"\f04d"}.fa-forward:before{content:"\f04e"}.fa-fast-forward:before{content:"\f050"}.fa-step-forward:before{content:"\f051"}.fa-eject:before{content:"\f052"}.fa-chevron-left:before{content:"\f053"}.fa-chevron-right:before{content:"\f054"}.fa-plus-circle:before{content:"\f055"}.fa-minus-circle:before{content:"\f056"}.fa-times-circle:before{content:"\f057"}.fa-check-circle:before{content:"\f058"}.fa-question-circle:before{content:"\f059"}.fa-info-circle:before{content:"\f05a"}.fa-crosshairs:before{content:"\f05b"}.fa-times-circle-o:before{content:"\f05c"}.fa-check-circle-o:before{content:"\f05d"}.fa-ban:before{content:"\f05e"}.fa-arrow-left:before{content:"\f060"}.fa-arrow-right:before{content:"\f061"}.fa-arrow-up:before{content:"\f062"}.fa-arrow-down:before{content:"\f063"}.fa-mail-forward:before,.fa-share:before{content:"\f064"}.fa-expand:before{content:"\f065"}.fa-compress:before{content:"\f066"}.fa-plus:before{content:"\f067"}.fa-minus:before{content:"\f068"}.fa-asterisk:before{content:"\f069"}.fa-exclamation-circle:before{content:"\f06a"}.fa-gift:before{content:"\f06b"}.fa-leaf:before{content:"\f06c"}.fa-fire:before{content:"\f06d"}.fa-eye:before{content:"\f06e"}.fa-eye-slash:before{content:"\f070"}.fa-warning:before,.fa-exclamation-triangle:before{content:"\f071"}.fa-plane:before{content:"\f072"}.fa-calendar:before{content:"\f073"}.fa-random:before{content:"\f074"}.fa-comment:before{content:"\f075"}.fa-magnet:before{content:"\f076"}.fa-chevron-up:before{content:"\f077"}.fa-chevron-down:before{content:"\f078"}.fa-retweet:before{content:"\f079"}.fa-shopping-cart:before{content:"\f07a"}.fa-folder:before{content:"\f07b"}.fa-folder-open:before{content:"\f07c"}.fa-arrows-v:before{content:"\f07d"}.fa-arrows-h:before{content:"\f07e"}.fa-bar-chart-o:before,.fa-bar-chart:before{content:"\f080"}.fa-twitter-square:before{content:"\f081"}.fa-facebook-square:before{content:"\f082"}.fa-camera-retro:before{content:"\f083"}.fa-key:before{content:"\f084"}.fa-gears:before,.fa-cogs:before{content:"\f085"}.fa-comments:before{content:"\f086"}.fa-thumbs-o-up:before{content:"\f087"}.fa-thumbs-o-down:before{content:"\f088"}.fa-star-half:before{content:"\f089"}.fa-heart-o:before{content:"\f08a"}.fa-sign-out:before{content:"\f08b"}.fa-linkedin-square:before{content:"\f08c"}.fa-thumb-tack:before{content:"\f08d"}.fa-external-link:before{content:"\f08e"}.fa-sign-in:before{content:"\f090"}.fa-trophy:before{content:"\f091"}.fa-github-square:before{content:"\f092"}.fa-upload:before{content:"\f093"}.fa-lemon-o:before{content:"\f094"}.fa-phone:before{content:"\f095"}.fa-square-o:before{content:"\f096"}.fa-bookmark-o:before{content:"\f097"}.fa-phone-square:before{content:"\f098"}.fa-twitter:before{content:"\f099"}.fa-facebook:before{content:"\f09a"}.fa-github:before{content:"\f09b"}.fa-unlock:before{content:"\f09c"}.fa-credit-card:before{content:"\f09d"}.fa-rss:before{content:"\f09e"}.fa-hdd-o:before{content:"\f0a0"}.fa-bullhorn:before{content:"\f0a1"}.fa-bell:before{content:"\f0f3"}.fa-certificate:before{content:"\f0a3"}.fa-hand-o-right:before{content:"\f0a4"}.fa-hand-o-left:before{content:"\f0a5"}.fa-hand-o-up:before{content:"\f0a6"}.fa-hand-o-down:before{content:"\f0a7"}.fa-arrow-circle-left:before{content:"\f0a8"}.fa-arrow-circle-right:before{content:"\f0a9"}.fa-arrow-circle-up:before{content:"\f0aa"}.fa-arrow-circle-down:before{content:"\f0ab"}.fa-globe:before{content:"\f0ac"}.fa-wrench:before{content:"\f0ad"}.fa-tasks:before{content:"\f0ae"}.fa-filter:before{content:"\f0b0"}.fa-briefcase:before{content:"\f0b1"}.fa-arrows-alt:before{content:"\f0b2"}.fa-group:before,.fa-users:before{content:"\f0c0"}.fa-chain:before,.fa-link:before{content:"\f0c1"}.fa-cloud:before{content:"\f0c2"}.fa-flask:before{content:"\f0c3"}.fa-cut:before,.fa-scissors:before{content:"\f0c4"}.fa-copy:before,.fa-files-o:before{content:"\f0c5"}.fa-paperclip:before{content:"\f0c6"}.fa-save:before,.fa-floppy-o:before{content:"\f0c7"}.fa-square:before{content:"\f0c8"}.fa-navicon:before,.fa-reorder:before,.fa-bars:before{content:"\f0c9"}.fa-list-ul:before{content:"\f0ca"}.fa-list-ol:before{content:"\f0cb"}.fa-strikethrough:before{content:"\f0cc"}.fa-underline:before{content:"\f0cd"}.fa-table:before{content:"\f0ce"}.fa-magic:before{content:"\f0d0"}.fa-truck:before{content:"\f0d1"}.fa-pinterest:before{content:"\f0d2"}.fa-pinterest-square:before{content:"\f0d3"}.fa-google-plus-square:before{content:"\f0d4"}.fa-google-plus:before{content:"\f0d5"}.fa-money:before{content:"\f0d6"}.fa-caret-down:before{content:"\f0d7"}.fa-caret-up:before{content:"\f0d8"}.fa-caret-left:before{content:"\f0d9"}.fa-caret-right:before{content:"\f0da"}.fa-columns:before{content:"\f0db"}.fa-unsorted:before,.fa-sort:before{content:"\f0dc"}.fa-sort-down:before,.fa-sort-desc:before{content:"\f0dd"}.fa-sort-up:before,.fa-sort-asc:before{content:"\f0de"}.fa-envelope:before{content:"\f0e0"}.fa-linkedin:before{content:"\f0e1"}.fa-rotate-left:before,.fa-undo:before{content:"\f0e2"}.fa-legal:before,.fa-gavel:before{content:"\f0e3"}.fa-dashboard:before,.fa-tachometer:before{content:"\f0e4"}.fa-comment-o:before{content:"\f0e5"}.fa-comments-o:before{content:"\f0e6"}.fa-flash:before,.fa-bolt:before{content:"\f0e7"}.fa-sitemap:before{content:"\f0e8"}.fa-umbrella:before{content:"\f0e9"}.fa-paste:before,.fa-clipboard:before{content:"\f0ea"}.fa-lightbulb-o:before{content:"\f0eb"}.fa-exchange:before{content:"\f0ec"}.fa-cloud-download:before{content:"\f0ed"}.fa-cloud-upload:before{content:"\f0ee"}.fa-user-md:before{content:"\f0f0"}.fa-stethoscope:before{content:"\f0f1"}.fa-suitcase:before{content:"\f0f2"}.fa-bell-o:before{content:"\f0a2"}.fa-coffee:before{content:"\f0f4"}.fa-cutlery:before{content:"\f0f5"}.fa-file-text-o:before{content:"\f0f6"}.fa-building-o:before{content:"\f0f7"}.fa-hospital-o:before{content:"\f0f8"}.fa-ambulance:before{content:"\f0f9"}.fa-medkit:before{content:"\f0fa"}.fa-fighter-jet:before{content:"\f0fb"}.fa-beer:before{content:"\f0fc"}.fa-h-square:before{content:"\f0fd"}.fa-plus-square:before{content:"\f0fe"}.fa-angle-double-left:before{content:"\f100"}.fa-angle-double-right:before{content:"\f101"}.fa-angle-double-up:before{content:"\f102"}.fa-angle-double-down:before{content:"\f103"}.fa-angle-left:before{content:"\f104"}.fa-angle-right:before{content:"\f105"}.fa-angle-up:before{content:"\f106"}.fa-angle-down:before{content:"\f107"}.fa-desktop:before{content:"\f108"}.fa-laptop:before{content:"\f109"}.fa-tablet:before{content:"\f10a"}.fa-mobile-phone:before,.fa-mobile:before{content:"\f10b"}.fa-circle-o:before{content:"\f10c"}.fa-quote-left:before{content:"\f10d"}.fa-quote-right:before{content:"\f10e"}.fa-spinner:before{content:"\f110"}.fa-circle:before{content:"\f111"}.fa-mail-reply:before,.fa-reply:before{content:"\f112"}.fa-github-alt:before{content:"\f113"}.fa-folder-o:before{content:"\f114"}.fa-folder-open-o:before{content:"\f115"}.fa-smile-o:before{content:"\f118"}.fa-frown-o:before{content:"\f119"}.fa-meh-o:before{content:"\f11a"}.fa-gamepad:before{content:"\f11b"}.fa-keyboard-o:before{content:"\f11c"}.fa-flag-o:before{content:"\f11d"}.fa-flag-checkered:before{content:"\f11e"}.fa-terminal:before{content:"\f120"}.fa-code:before{content:"\f121"}.fa-mail-reply-all:before,.fa-reply-all:before{content:"\f122"}.fa-star-half-empty:before,.fa-star-half-full:before,.fa-star-half-o:before{content:"\f123"}.fa-location-arrow:before{content:"\f124"}.fa-crop:before{content:"\f125"}.fa-code-fork:before{content:"\f126"}.fa-unlink:before,.fa-chain-broken:before{content:"\f127"}.fa-question:before{content:"\f128"}.fa-info:before{content:"\f129"}.fa-exclamation:before{content:"\f12a"}.fa-superscript:before{content:"\f12b"}.fa-subscript:before{content:"\f12c"}.fa-eraser:before{content:"\f12d"}.fa-puzzle-piece:before{content:"\f12e"}.fa-microphone:before{content:"\f130"}.fa-microphone-slash:before{content:"\f131"}.fa-shield:before{content:"\f132"}.fa-calendar-o:before{content:"\f133"}.fa-fire-extinguisher:before{content:"\f134"}.fa-rocket:before{content:"\f135"}.fa-maxcdn:before{content:"\f136"}.fa-chevron-circle-left:before{content:"\f137"}.fa-chevron-circle-right:before{content:"\f138"}.fa-chevron-circle-up:before{content:"\f139"}.fa-chevron-circle-down:before{content:"\f13a"}.fa-html5:before{content:"\f13b"}.fa-css3:before{content:"\f13c"}.fa-anchor:before{content:"\f13d"}.fa-unlock-alt:before{content:"\f13e"}.fa-bullseye:before{content:"\f140"}.fa-ellipsis-h:before{content:"\f141"}.fa-ellipsis-v:before{content:"\f142"}.fa-rss-square:before{content:"\f143"}.fa-play-circle:before{content:"\f144"}.fa-ticket:before{content:"\f145"}.fa-minus-square:before{content:"\f146"}.fa-minus-square-o:before{content:"\f147"}.fa-level-up:before{content:"\f148"}.fa-level-down:before{content:"\f149"}.fa-check-square:before{content:"\f14a"}.fa-pencil-square:before{content:"\f14b"}.fa-external-link-square:before{content:"\f14c"}.fa-share-square:before{content:"\f14d"}.fa-compass:before{content:"\f14e"}.fa-toggle-down:before,.fa-caret-square-o-down:before{content:"\f150"}.fa-toggle-up:before,.fa-caret-square-o-up:before{content:"\f151"}.fa-toggle-right:before,.fa-caret-square-o-right:before{content:"\f152"}.fa-euro:before,.fa-eur:before{content:"\f153"}.fa-gbp:before{content:"\f154"}.fa-dollar:before,.fa-usd:before{content:"\f155"}.fa-rupee:before,.fa-inr:before{content:"\f156"}.fa-cny:before,.fa-rmb:before,.fa-yen:before,.fa-jpy:before{content:"\f157"}.fa-ruble:before,.fa-rouble:before,.fa-rub:before{content:"\f158"}.fa-won:before,.fa-krw:before{content:"\f159"}.fa-bitcoin:before,.fa-btc:before{content:"\f15a"}.fa-file:before{content:"\f15b"}.fa-file-text:before{content:"\f15c"}.fa-sort-alpha-asc:before{content:"\f15d"}.fa-sort-alpha-desc:before{content:"\f15e"}.fa-sort-amount-asc:before{content:"\f160"}.fa-sort-amount-desc:before{content:"\f161"}.fa-sort-numeric-asc:before{content:"\f162"}.fa-sort-numeric-desc:before{content:"\f163"}.fa-thumbs-up:before{content:"\f164"}.fa-thumbs-down:before{content:"\f165"}.fa-youtube-square:before{content:"\f166"}.fa-youtube:before{content:"\f167"}.fa-xing:before{content:"\f168"}.fa-xing-square:before{content:"\f169"}.fa-youtube-play:before{content:"\f16a"}.fa-dropbox:before{content:"\f16b"}.fa-stack-overflow:before{content:"\f16c"}.fa-instagram:before{content:"\f16d"}.fa-flickr:before{content:"\f16e"}.fa-adn:before{content:"\f170"}.fa-bitbucket:before{content:"\f171"}.fa-bitbucket-square:before{content:"\f172"}.fa-tumblr:before{content:"\f173"}.fa-tumblr-square:before{content:"\f174"}.fa-long-arrow-down:before{content:"\f175"}.fa-long-arrow-up:before{content:"\f176"}.fa-long-arrow-left:before{content:"\f177"}.fa-long-arrow-right:before{content:"\f178"}.fa-apple:before{content:"\f179"}.fa-windows:before{content:"\f17a"}.fa-android:before{content:"\f17b"}.fa-linux:before{content:"\f17c"}.fa-dribbble:before{content:"\f17d"}.fa-skype:before{content:"\f17e"}.fa-foursquare:before{content:"\f180"}.fa-trello:before{content:"\f181"}.fa-female:before{content:"\f182"}.fa-male:before{content:"\f183"}.fa-gittip:before{content:"\f184"}.fa-sun-o:before{content:"\f185"}.fa-moon-o:before{content:"\f186"}.fa-archive:before{content:"\f187"}.fa-bug:before{content:"\f188"}.fa-vk:before{content:"\f189"}.fa-weibo:before{content:"\f18a"}.fa-renren:before{content:"\f18b"}.fa-pagelines:before{content:"\f18c"}.fa-stack-exchange:before{content:"\f18d"}.fa-arrow-circle-o-right:before{content:"\f18e"}.fa-arrow-circle-o-left:before{content:"\f190"}.fa-toggle-left:before,.fa-caret-square-o-left:before{content:"\f191"}.fa-dot-circle-o:before{content:"\f192"}.fa-wheelchair:before{content:"\f193"}.fa-vimeo-square:before{content:"\f194"}.fa-turkish-lira:before,.fa-try:before{content:"\f195"}.fa-plus-square-o:before{content:"\f196"}.fa-space-shuttle:before{content:"\f197"}.fa-slack:before{content:"\f198"}.fa-envelope-square:before{content:"\f199"}.fa-wordpress:before{content:"\f19a"}.fa-openid:before{content:"\f19b"}.fa-institution:before,.fa-bank:before,.fa-university:before{content:"\f19c"}.fa-mortar-board:before,.fa-graduation-cap:before{content:"\f19d"}.fa-yahoo:before{content:"\f19e"}.fa-google:before{content:"\f1a0"}.fa-reddit:before{content:"\f1a1"}.fa-reddit-square:before{content:"\f1a2"}.fa-stumbleupon-circle:before{content:"\f1a3"}.fa-stumbleupon:before{content:"\f1a4"}.fa-delicious:before{content:"\f1a5"}.fa-digg:before{content:"\f1a6"}.fa-pied-piper:before{content:"\f1a7"}.fa-pied-piper-alt:before{content:"\f1a8"}.fa-drupal:before{content:"\f1a9"}.fa-joomla:before{content:"\f1aa"}.fa-language:before{content:"\f1ab"}.fa-fax:before{content:"\f1ac"}.fa-building:before{content:"\f1ad"}.fa-child:before{content:"\f1ae"}.fa-paw:before{content:"\f1b0"}.fa-spoon:before{content:"\f1b1"}.fa-cube:before{content:"\f1b2"}.fa-cubes:before{content:"\f1b3"}.fa-behance:before{content:"\f1b4"}.fa-behance-square:before{content:"\f1b5"}.fa-steam:before{content:"\f1b6"}.fa-steam-square:before{content:"\f1b7"}.fa-recycle:before{content:"\f1b8"}.fa-automobile:before,.fa-car:before{content:"\f1b9"}.fa-cab:before,.fa-taxi:before{content:"\f1ba"}.fa-tree:before{content:"\f1bb"}.fa-spotify:before{content:"\f1bc"}.fa-deviantart:before{content:"\f1bd"}.fa-soundcloud:before{content:"\f1be"}.fa-database:before{content:"\f1c0"}.fa-file-pdf-o:before{content:"\f1c1"}.fa-file-word-o:before{content:"\f1c2"}.fa-file-excel-o:before{content:"\f1c3"}.fa-file-powerpoint-o:before{content:"\f1c4"}.fa-file-photo-o:before,.fa-file-picture-o:before,.fa-file-image-o:before{content:"\f1c5"}.fa-file-zip-o:before,.fa-file-archive-o:before{content:"\f1c6"}.fa-file-sound-o:before,.fa-file-audio-o:before{content:"\f1c7"}.fa-file-movie-o:before,.fa-file-video-o:before{content:"\f1c8"}.fa-file-code-o:before{content:"\f1c9"}.fa-vine:before{content:"\f1ca"}.fa-codepen:before{content:"\f1cb"}.fa-jsfiddle:before{content:"\f1cc"}.fa-life-bouy:before,.fa-life-buoy:before,.fa-life-saver:before,.fa-support:before,.fa-life-ring:before{content:"\f1cd"}.fa-circle-o-notch:before{content:"\f1ce"}.fa-ra:before,.fa-rebel:before{content:"\f1d0"}.fa-ge:before,.fa-empire:before{content:"\f1d1"}.fa-git-square:before{content:"\f1d2"}.fa-git:before{content:"\f1d3"}.fa-hacker-news:before{content:"\f1d4"}.fa-tencent-weibo:before{content:"\f1d5"}.fa-qq:before{content:"\f1d6"}.fa-wechat:before,.fa-weixin:before{content:"\f1d7"}.fa-send:before,.fa-paper-plane:before{content:"\f1d8"}.fa-send-o:before,.fa-paper-plane-o:before{content:"\f1d9"}.fa-history:before{content:"\f1da"}.fa-circle-thin:before{content:"\f1db"}.fa-header:before{content:"\f1dc"}.fa-paragraph:before{content:"\f1dd"}.fa-sliders:before{content:"\f1de"}.fa-share-alt:before{content:"\f1e0"}.fa-share-alt-square:before{content:"\f1e1"}.fa-bomb:before{content:"\f1e2"}.fa-soccer-ball-o:before,.fa-futbol-o:before{content:"\f1e3"}.fa-tty:before{content:"\f1e4"}.fa-binoculars:before{content:"\f1e5"}.fa-plug:before{content:"\f1e6"}.fa-slideshare:before{content:"\f1e7"}.fa-twitch:before{content:"\f1e8"}.fa-yelp:before{content:"\f1e9"}.fa-newspaper-o:before{content:"\f1ea"}.fa-wifi:before{content:"\f1eb"}.fa-calculator:before{content:"\f1ec"}.fa-paypal:before{content:"\f1ed"}.fa-google-wallet:before{content:"\f1ee"}.fa-cc-visa:before{content:"\f1f0"}.fa-cc-mastercard:before{content:"\f1f1"}.fa-cc-discover:before{content:"\f1f2"}.fa-cc-amex:before{content:"\f1f3"}.fa-cc-paypal:before{content:"\f1f4"}.fa-cc-stripe:before{content:"\f1f5"}.fa-bell-slash:before{content:"\f1f6"}.fa-bell-slash-o:before{content:"\f1f7"}.fa-trash:before{content:"\f1f8"}.fa-copyright:before{content:"\f1f9"}.fa-at:before{content:"\f1fa"}.fa-eyedropper:before{content:"\f1fb"}.fa-paint-brush:before{content:"\f1fc"}.fa-birthday-cake:before{content:"\f1fd"}.fa-area-chart:before{content:"\f1fe"}.fa-pie-chart:before{content:"\f200"}.fa-line-chart:before{content:"\f201"}.fa-lastfm:before{content:"\f202"}.fa-lastfm-square:before{content:"\f203"}.fa-toggle-off:before{content:"\f204"}.fa-toggle-on:before{content:"\f205"}.fa-bicycle:before{content:"\f206"}.fa-bus:before{content:"\f207"}.fa-ioxhost:before{content:"\f208"}.fa-angellist:before{content:"\f209"}.fa-cc:before{content:"\f20a"}.fa-shekel:before,.fa-sheqel:before,.fa-ils:before{content:"\f20b"}.fa-meanpath:before{content:"\f20c"} \ No newline at end of file diff --git a/resources/report/fonts/fontawesome-webfont.woff b/resources/report/fonts/fontawesome-webfont.woff index 9eaecb37996e205f1027fce2df59fbaa500657a8..628b6a52a87e62c6f22426e17c01f6a303aa194e 100644 GIT binary patch literal 65452 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 nJ|~_<0`h#ayM?eMWNCCuUAro&VV7-HmUD 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 literal 83760 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 i9b$7!i z{C7xjc+N7FQ8!Gy#Hd5bHz~z`f`3%arn$#s_OrY)>W%;N=@Iv=c`xP8a(Bo7Q(C)? zXYNGrnMaOjPx`vkUpLj>b&|VTq)x4M%}xJF?}e`}-Glek#FPwg}i(l^kQ-+ z=Zq!lLi!VvIxj@&OntO8Kga6P?ThJ+r5($y(mZ!H-#${fO+le($*!B}%t4zDEI)nH zj&W{t?W)i>!UpGh&i;PWdekAOTyS}OB;VYv==JzeLUr#?h z<>%&8|1K=PGn*?uc1c7>(m(0BB?Vctbe{DsVoqY$3!L7#e=b9`R`^@VRGqHFEIqHd zO&=!SDxa}-^|FW?-6tPZmtRW#!dA`h&vV6W!Hgm?jyE|siyUTTQd!yTn^xg(FNk4w&18b3QboL^igRvx_&?{b}c>LZcx4c6g1j;wSDc*~!D?{vd_)ips6W0!^< z>N!xpviPb+maplbT@8kJBxJenePs75dVEoRzQwmiFWm3{V2`U_xBiylzK`AUcYn=# zB&7bhvvcK*OG&lCf9LU<9yUGp;TZ4NWa$~+G1-&%rmf##`Sga_49+{%uQUEncJH&b zoRQ}DapS&C{x*|WmbLqi*NR0_ihI>Wv0FddyIP%B$jMoG z&8|Jd^z6}{t4Hr#o%W}6%}IYoDGifK5uFg{qILRnWUAvn9!O)$a*?JSt?R+Z3F8HQ3clSD`mxsL*hdLhQhCBh@jA@b<~i?>0J2Q;Nt9(<{5{I=KqzuAVY#xG~BUwjHT z>$9z#a_7aLX6q*Bi^nz?Zs=QYc-1N^#_CbC>%x+C?|16o`x?+Uf$^aJzKS=TR_`Yl zK3guf{>Ik7+3|N?d}h7&wf%L4<0JDnU(+LLrB)`=-!8n{utj3_q=@N)Cnl=@cF*5y zK0)%%Gml)cjO7z@Z+(0s^j5hx*}pbm){avzJ^1Y^O$-A+24DYCmUBAgM~?5BtNI*T zb=k*mDz^M_ynetVMQ!Fbe?8mvGj5(L6e`K>EZkfY_rosS;?$=k#@$a1+HM7We8=$X zF5jDlz1DK9rzK;-=o6V>+48ob$qX&jQ7SfWCuo zoQ{4Ev@H@m)T40p;8NMQ_xNiQ3iwZavd*|~khiq^o5+`$thax4Y6p~CRn3@}yQJIy z-vNQQmVW1i9m=d7*~;v1S5=iIb(}Dk@KNr zem4_0l_xsPm%k)0aCmRCNz#N(Qnd@d7^T>*FKIVDrm^kPsflxR`@R2Nat>GYe6o4^ z9KUO`s#m2=@b)wI-lk>edhK1|tyk)qyP3@@mT_#Gch*DrQS-C8TAL~tPH+lTyy|a# z;9SN#mSg8EB2M_E7QI-}u}19Hirw8i?@s%}kysb*UB`Zg!*E9Iih_-y{O{B|`cIat zG*s=?W_30nb0%1ji{Ct7c6( z_{uTbytSHhL;VlgGjm!0&puLgd%fJ;ny)Y3#C?CVQQ5yNf8SG|Z8i*#J3ISIz9z&T zI=E`8mh;w2>~+7t1g&3ox!XuGbQ%AQTqbdUGpUV6S3lGT=Vpg*a8}|nnkU-o>1w@J zp|)~nEc2GY^&6!W4RiLYxa{BCD4@Q;No~=Rrkt6t!UBY@uAbm>Ywhn7bGF{zbv~=M z_Yarw(~|W!bAG>AcD`t z@zdf3S37^i)m`8HXu_({h8jt4!5aCdj{Ywvqz=s8xS;)ySEZnlyS#wh?7eB8+s&pd z|D+bMOFDb$pK013`@;6zmdX{2sM~(vlv#86cMxiTq+C2MEc z*XWIzdRZG+KAj%7*h}xKxU_zq{`F7QJHz&bKi>VtRs3MM;+o$xJz34f;&XU6oV!{Y zUw5?oUN)2UimyUgeG)UKAKuO(WCHaE_gZ0RuJET7KBFJYQxd_G&wg_H-0dX;>5P<%W)^q@e& z?zV=q5ROI496=2ScUgOU&?roDsAKrEYo&|9Q=fW0zto%lX}(l)v~BsK{oMPVQ>)U;Pjsq=tXt4| zK;Pt$?(TqgDJrJBJG=Lpg$U~&y4)Rl#P7A}4o2s@Tzi+? zQrU6fbla7=j=v<-1h-}MUR!*KQ|~nU07#m8ll?w+*NnI(vfrCex3%OTpo0W9evGfX4<&njoa3XY#;BjO`PsB z@!u+kD}qxabsOz(>vBpt>b|Vl>$X<$!~Dp#mjx&5ScPOw%(&vRdYX!7cEIW-Y>sES z7fqhddNAusBujJHgv!mq-#(;?>R+6{VMbH0(R-m5sYde`onG0GO07g6p8YbD#nUxk zZN-WYS}#~PyDqAq^(?ggF~@=Xn^Tn{qutC+V!CGf&+m#x>9PMUS6?iU|hqxhC1 z3&fbxPI^3Not+}Ig>9{h#2G2siMmpYrkY3{T)p|~s_amqi?4h3cpjB5{UWZ~xo@Gr z`n3}uel=wXSy_c@ojhcor83#;?WWIJaVE1(#I7dS^!$IexXE|Js*b2^!HT&n!dE`L zSoz4nn{92J>c=hRo=uV2LcKP%;`feqH{A+5-7R+7wPTxnfN)aaN|UNbQ(bT6sNI@$ zL|mwIVXVL*sY9=~YH2PAs@z%>aEgQYEy5mxb$($ zJ=a^kQm(VxB-U0rriOM-TGl51>P+3DrLpe0qNb)z)0R(l)Skn|CbqcIuF=;Zo260Q zbgkIj_-!B38W~n=yq(Y#w$xlGa@AI@MGo1H6MS|V+@16_t2b=5;2JaCi6)EAE?T;O ziMY-l$K@AST-Az8Ubx@qi&FlQdmNHKDjS?>(Jj~ph zoz3FOf92dHKX?5F`iF!)RfR4t651*icd1Kjt#80gm905TwqLgh*~3vAT{P?NB)4pn zEY&0RW}u8EtRrjD_P>^yygr0mM^U_Th8z7j7(NyGk*IzYwaw#E1fNU?icmE z@&dI5CWdFfa9D8o$eV@z3slv%rd;f5@=9%BQ%L#s=XvO^W&M}97BA{yTovm)Thgu9 zA-k*0I8ODV;LEU!^VU4y+LW%x4s`gxXuj6!V_g)U}I)6bMuCqGVZGXD$)9&qQ`8lgV zC(L8fY7NeX24e9%o9|u!(6{E>#P#=R=o1QnYE|xUh&Gg zm*T1%!x-wh9xf^0bSd|R{)Qr!1!-#=t}?#mzUS#?uvjfM$^3vauUFCPBU?`uIiGA> zlJ~w~+oZLQf9f=@1ch(Xt(gs<8 zQO{=Fy}@sN#hO2TMjqShU9DBZpS*XLZg}1`fBB=twrgMiG(OyZQQtMK`p|<`<;{oL z&!tzcW0`sG^OHL^SKim0bU*!}eDa$Qj4XXircd3pN57i!Zg}X=J<UbtRy!t4K@4P(UReLACsq^ZNJTsIyByg0a*O`B!bH9Uw zNJ5?x=OyK(%U>?sHBF$QC~4-U%U_H%m_Pc@e8t^(i$kwv_T$vA3k`PrY+Ac#&8N=+ zPA9XUUx_?&v#2;TPj-9f?c;mpm4; z7Q^Y~rNbh$(B7hAch;Y0`z9u4zTWKq?rzznrT$h|`QpF-(q=C?eEIvm^7mghJrhZFbBJ|4P#{++V-g8w9oT(gf{jrsmS^X0a+ zeshfAuU#?@ zj?ND@xFQ!gcgnp-voiVZj@3?T=6UPs({Z>}QM@rK?}%0VnlF|iQ=5*)On54JS#5Q* zkaV}@T-E)&nmaxpS4>dnxKu=dV{9Bgm zoxS(L<=aFTd*W!d=Jr{`vo@Zu2(PH??{p&A$0@ z?abNvw|7>X@BMn}?tZ?@(dHbyZ2h-o-UZ(NVz+Ri>6^dPwtq8xAH;ii#aEkWyceC~ z?w@i>)e-IyT(NX@{6XH$h6*Vm_0p2FJDkq6n<&NHd%_UriyOY;A|xpQ;c_x&H989x_i6fOMtg@5A z&&+l?o5N{-Vduq;8z<}XCN&%MNFDfbCi>N*!ZSVDF8xW)8x<17<}65zEQtFeD7Ge! zXWc=Kq9Zez@`NWiSnZy3P^4KZut-BGDlvJCKWl9tvKKJbwYfyfQEA5sR{Al zd(O^1|F7eJ)l1##YxDMI_dihM-+bW0rBd;K-{Mox68BnO}L%@#Xi&q&(>^@$YWM<>JNHk1HI`;J328^M%!3`CoLs-+a{IHs`4-KAH_D^MOJvpM z8_wE(YBDT%>#Jk7`@!yCQY;3}XAS!-AI)gtewepV;aJh4MSMHooYGim9o2NsHReO$ zWfM*9knN|AKC)0O3qEUIxL*3?8%Fh8tbz`j;+%r+C#JGwG42pDdOG#xIoF^selE2I zw_hGlbK80>I^Q(QJzdUv@7o1YS)Ffo{J(hFnEmP^&nq#9#eFs%ow0U0OTMSl^SwH0Di!5WTk!15;_q+o{O*l#&-ncCZ}iRUwj0;}=FjIV-Jt&|SvOSHcTsxX zH2dkXkDjIfU8XB{P$lr-zxNv?w|{=U+57+0=kw=PXzbj3aK+s%p4mA!=G9~@dhe2P z`r8rb$#Y{}WYoTAT#@u%a58S!zLLFrH4{z-%>6tsabiiSU!BIz+N|H({kNNaJ^HZu z|IwEf@xj_PI&-gmSd<}XyV=fevS#kyynW&KQ?9$%Hnnnndcwa!`fkv#nl_uC4F{6S zX7pTXSaC9Q-TZ2i=hyV6xYQnvk@^{WYofYJYCxJCEx{ zs?D;5qc1Nm*LN>Fa^sG-`qP>#$0s#5$9~x@zM}AU=63FHm*=HTD?V1Dw@0QVf>C@@ z_=$Bh7EJn-%s7)Xtc3po=jq#t`jwZgrP*xWUaV_d#VhFR{rr$^NY|qD-`wO@-Jx-pkDOQfV)4PMC3V^TdLJW%2@RUif-Ec`KU~cJqj(U(NF^CA&+k z&5ztY(ijrZywNYDYJ^SMF~1 z9~%$Pw|ENnp!fBoNp~d5XK3G0Jhe)0(VCPc-wTyHv!(tR z{k*WtBDpB4|7+(;mK(ydh8=bNqKZ#y7d&e0-2C8s759ckj(gsJ{eKg+G;O=Yn!>t9=))d}e9dc(B+ z2;-wv$*!yF7lRV>U#4%F9M{mWyEpYkxnlOKOM=_a#kp;=p!kf`@M70PxTas_{L-hPkbqU zwV{2TTiJ7gsZwSI>QiDI@(q`_9rZo1?xNdMhZ~p08}Dq{Kcm=?U$^O;gU-CxqmLxt zgaqGX;oiDk(&y%Z=Oqe!+jzvCZO=IL_$KN!XS6HdI?<$M?B?zE=)uE|<3(ZK z>)4}s949CI`s~0J*U!qByZEQ|%aj|O8Lxh|2^?zaIr;NJn$^?PHS0T~HXpu!>G+G? z-_MrZoDctiKpy1>-Z7Yo;(jhe~GcuR=k1gn#4hQQ;b zgI6W}kIDX9;9J;u$+$-A<_azgrV!8YC+FN6&xvmdF`BpFR;|O*f3dsUEUj#0))tqu zlwFCrxBKOX7uyVru5Y{)Id#T6uj{UTl_s&iW~Z%A%go$kbFcpEwVgj|i`BhCsvnxJ zeZsjqbLZxe{P1$6PenD=N|&A$UH|s&=w)N+Bx704^8d!Z-t%wVjeCAJqpCz%H|&u5 z{5!SHiN!Tl`(HiV?WN8qn^kF+Ghz1qf9G8%Z@qMMm6`V5wN}TD`J}(o-g!ADk;m%F zzodr(r@nA3zseKL&A5Y;`^a32@@%@z~#j~I$ZO>7? zC%YMEsPJSKO?fQ)=L>_&A=O}=`eRE!>~XvnaAN%hkLic+H67rayJ1$yjIY0E_nh?F z^u4a3V`K2)>#x43o!oF&#QWX8ufHx%eE9HvpX}S*xT5OVxnEm8gwK3^HfVvZ(T(kz z#&$R5?%t|sv00i|SZbC(=blOJ?XS`HGt9Cp82w)Wzks}m-LXY7+= zD=>Ch6yMuZODF}7rn&6es$1kwu3g4&V5~8%$)gd>cNF~ zYyUD^mrr%BJbC(y$5lojqwF@1RZ{A*KlXlle&^oCuk8z~-)w!h{Vl`QH14Tu#f~lW zzr)~u{ApA1<+PCKhF$AswFS9-(S5_UamuZy0UP}um+Z(1o!e46h40$hGb&TMcF)la zUwYZ0a{1YvcbW}0ajnVUk!b39qyOGA-n=z${paM}+4;8itL@j8_vgP{W}QDH+34Ya&{FTBKJJgj^DZ9&Gdat({=YQc@q??y7)$n&>e=WA!<9rcOJ5O zab5Z`gPRaTR>L0qj+=@KeSSwARbM7n+_&xcp38nSQ)^c6e#U^#tQN13=GBc_Cv$%p zIUnG7yK7qB0u>E0C*=S&7KiPM%VP31o|$dfDm*9YF~?Oe|L5B;tafXA@#Oj?u7^vd zUxWoSEZg(K%IYaEZ~hIQN&e-ldGt1&TPLDWtJ2iWRABRU>QQkkGoK`b15H;xPF~e3 zyNH+Lb>oF?Je4Y1_h&9>7YNKYt~+ZMVlDrrV~+ZYjWhqWO=vKS{WVe0iEaPMWsxd3 z{Ux^6uRE(G&@th_dRPAmDJFN%W#lUFZB3u}P-Awi+FAz=mQ9E4omkeMblvA_QMGg9 z6Bh-+Z`%)@-#GI(gWLH4UF+uTDBbRblKO|I{?Zk&X-=zJrn>2duj)FshzV}D6z}aS zJ?thn>wDLN%~#64NgNBfzfH^~+I&`Pu0vMN4US1G=3HETWzNy3`FZ{2{h{jH4Chov zC?Ck<7o6(xkvYLuPb@(&$;%@6V6&#`J*gC7$ERGMLK}te@BCIV-}iRjeCZueyWR7D zEpPAJTXTKii7zR8+sr>`S^k?VKELAQzsJn8eP^YGm**5L|2;vcZga@VROj;D?>F)G z{tWo_Z~M8p|6i@E)8FqXfAT`ThHd_?;HR7T-_$<(eg5ue_y60n6$-NaopXNtlAXQF zi~XAXefPZetL}5YOFN@;x5e_$>kA1>R9^cndMjIOY@jhIi)Zl}uJcT)u{>N!U11+J zK6th&AM2ex;g`d|IorMcoCQks63^Za4%qwp&8DxSH?K;(@mO*#p5=|ehv~1cc&(nY zK16ffvG-9+8&g>;H8&kznp-UMy8h+z*ZI|z?_PM9zv<1HX=3FvcgdvW`&Ivx&(ELv zy8Ty)+HSV8D>7>)#z!s;yuWMrM}H?{zA&Kzx36SoV$Ws&b>R> zvePVVv--v~YeD9fmnYr#)c&+diJ5tZ)-%1$4L{~s_np2|x}|J6Tk7l6yyqJ9?@em^ zSa;L!*22Ha(uTYLb?ga{?vZixtV+>-duXdzkMjA9zq}{!{dl;#PtN)9y01?i(hJ@l zF}=Pn@cWGa+6GqV`5IUHFRVCqf5n2i8vitf3sn!uKV22Bt+6&^e$bZXd`d@UL(Y1! zO$u2XHBl-j|K0pqJm2mcnajL;%WJ-6tLc{GX=T&v_C7wT{NDaSiNxXhO}ex8X>Kc3 zOS=Af?Jl*&(W`B@ZcROXY}-Vi`l9TF9r~8C3jZgbO?er=m9s@cDLMCRTU+De*Sof< zDZS0rJ=o_f`#1X0%rh@zr{7h(vh#LQTgBbH^y3)^&P--2oxAhi&4igZQn>p*)f;Rm zet)v!|1??kI!pWcj{jGk_?Z#yr`Yz`!rXi7+xf*8GD^zBPgBE7Tok<;~-nOPnutT~x;4o$lL zAclYQbv=)M9lbAC-(5;Lma>*rCTgei#yc^F<*927%4Oc!luzM$b^Lk4=O3aasXN$& zW~r@sl#+3qU#)ikpGiwz%f;^Jm8uqhWPkM(Yq+m)M(A7SpqnMB(M-96j0r}Lo!gIi;~Y=c^xAm@sdtcG_jJB+Gr*Oy3&zKB;l z*fzJL^SnUNy0D2VFYXqyzqq;2cJ_P4P3sR{eE8>sxf!4Dzqg*B-Y|d9nfF2}`u^0L z+s!ZU-1tTR{G5N8yMA)NUcWmz_Wj3N&B>N2{?TqM-TIYZZq0mWS)G#LuVnGo(~R$I zYSi{!i~rQ`t$VZkzU{Y9*VwJLMMfLz`o=z*Znx)c^4-HT?>fuh+5NGNw|3^SWg92H zd~@aA%;@|XGvC^8{Z|n`SG_Rd!rhx9rKJ*9mG`b(DW3VE=J-VA+d}_teF@$B{oY31 zC-0+A&HeH3yZ@gL?Wub9rQ4E{Uq3I?eJr)bIim93BPUMrO-WOC7C%T@z`S9~Zk>`R zzYb-*e){RJ=FMM0zRl<5^CF7_ZoODGzp?z_A=w8nUUXmmTqf+#KKty|xm~9j+wCPM zFgx~3?e*KgaQ@Amo0G)EZhrnU`FWK3dzPJzeCPm8M3*v(xV&vj@A8%$yR z(JaTf;gz?fg56n;7sidYw?FO8c*-SNrq5jbBkb;Krq}+jo8p)?{&kyad8ODol$=@+ zo-^Yg;~b`#Y3zCY%IS|k=(Vi%dy^K{cDUalUUAaF-5ZxX&ZvF5&9TPlLvGqnpRao@ zYOn5{q&;Els`)7!f7RwX_N_j&-Kf}aUEk}_qRf|n5?qqf^e=b3TD^s|(LY0H!sffv)QZzDN$2$l3+*p- z{?&itSV;@(-!nd5-LLiRcdRVAUw3!c35V_70^#2sQs(BxzwDP{U;mMF-ns|t`L??4 z-nD4$_P@?6J|D8byiCa7N7mM0&(nz&FKgUn*Jf{un*D0gt26ppQS#}3wcJztgy+or zwuYnJmfg)Vf8&K7yEkd}v5Gti>en|(E%%5zWF4U!_^6ykqD0-c!ANR}s_f6hhg)QB zp3Aq+QJx+Dj8k!TMfK}8W#{?-%3e-gYu#RE@#WEUv-rZJ&wSbW=e-yF_pxcdjnBPT zZ)%QQzj^t?V|l&Wx!dJ-XX?bs$N$sE^ z7pC|W{}gjrX&|{<;ko(psh<~lIi70f(0cGVgyS4@ukS*IgdN8Z%JQC`y=h7)tM}d7 zIXC3~TYOZS`_td<-^@$#v1`?4{Vq-GuDbl%T(ns=5tDz5xzVAQ|cUpDa`=GQO`XyM-fIN&gW6YK*@pEC#;y|=-#fWL@PnOPex4oQk~>TLS(M)wl&>qT zeYs+~efpByzoM!_oX=ZTMD_if(Ybx~3trt_3VV0nTY1&#=7*!M?`zt-FT^+8x4d}A z$IqlxUAg7ojic8ur?36sy5WYQ{U^TO0MB>satCtljnOq1UIh zN`KB?@v4zSL1I&Bxc~#N`cvaOt0o-?ck`Rjxn1tp1l8s=9Q~j{blEL@8|y)u6y_1Q+|`c#NZ!WubBRH zsHocX|Cd|Q^5u6!UTfaf_2rVX3IC<4{pqw(uHa##&<~G(E3OJ>*Oq8-2?iT#u3uYFQF`HZQ!;O@xNeyLH-PptsDj&pUF2=Z-ceU300;Ml^PcK@){e{<|E~Ad+f$Onj z6MJ_UY^~;>rTL3b@z}o~S46K${EofG+N>|o=xqB*TdP$2x}njwk9!r~ZGN>jB#%k^ zdp%d1y|sC@>w=57r_GW2uW`}#Z^_H>rTNq9zMA~J`Cr27zwhmNZ(iQa+iv>8$DO-A z)}m_5hLHdFKK$ZzzxS}^_Dicr&v)EPJ*T};@-E9Oqczigos{i=dT%`DWOmEu((;q+ zri;$zT-E=3BtrdFO5~rcOus7;ya#y@-`VqIE5}3a&U-O& zyD#kD*1Ws_^jVkBYnwAf{>LP*skWW#o3zvSVhod}`|Biy$5)PB{Cd`4-!>6(vwX(w zI*-@gi#d~<_<{AA#E$zh8(ZJmF&N%x=qa<>5?aNWA@J6G;UlJ6Mc&O57_<3S%)8pM zsBo3H30wH1T&q8;SGY>{=rw%W^LyjG4{uzWo=2QuZo6~l(}DMrdXLrH(!KAfeiO(l zG&I~8u}_3g&re0{bnC}Ix2i>FR!=4Rd)M3+%CG9~BV)HJq3s@1}!pitCt6-}-`=UkzzTO|6{t-)JPbH=W zCOYJMCFMbe*`r~GF;;Bu<(;DU7(=2C|aa$L!H zG+Rr}>Bw|GlXsP0rt0te^kSa!+uFZLSKj8C^OfFM&hK;Ex~=DJUU|ry_u2N7WUp?0 zvFX@+iOpZCOWxcv=AW~(tmn+Fo{i3r&HCTE9MaH{`}L*t^|jdVFP;5kubUP+pSgWE zCi?cA6~$Lej@%OJ+!o>9yIPO&_^!PhrPX$=tA2G#_m|mUclp{ci@#)_o+_Px|I)pE zPrr2>e>U60;c>|kk;wMKHPspG?{?m5-4?MSsjlzp%3hHzVM{_-Ztaf{aq3K#@RG@1 z{#;6+ZP!9h8K;vP!8ThQWR5TW%)61ROE;+I*!04sne%myzt(;1xBd}3UzR7^kBX&{ zZ#+JmEj}3VYtpr}DQV$C-}c%1A2&~LdSv!kiLLB{z3knmw-c*X8Q15|6chA^xOdESQiX_HJPt{4ca;*E{#v$13DIwt z%3_aV-plsN?VR++JgHd@94$A_&+vJDqU%Pm+w1BT%IWuux~eS=woELW>wP^i^y-1% zm+yV>ysP^9#bUMWOu1&!mp_ahzg~L8mio_0XK!Ynx%uh8E!r~_Pi?mJ6u+`EDbIY( z9G=KI4PWPI9~N=AcFb>AMbxLYEv_@x9+R|BIC=CT!(ywBWP9d4%g!GC;}}(a`+(Cz z!;7nKY3i@o;vqN5ena@SeL2(iHuk;Uov?rP)Ke$t?K)Vxc*bJpHOt>B$UHY{2+Uzy zx354ZIdA*v^#z;uZ(Uu!+3}#t^;=ut?V8nhkZ01hx6{RA<^_rxUu5EGU)8rDx#i$K z=AIS$uIxq!3|37!te84?-7Wq$p$SQ6i|k)?=zTsPHFb$xZSnhyf$8smP5!KIzU1!m zlfN#%+qrq)yq9wKk6h&ZBllX_tXzt41D%)i0U z?=#=V(zf8nzutpwi`}K!jMJZgyR!Arq$^R|*;mL;`|g&Xb!Ba~$Cg`Xe&<uWiz;*MCX;Ix_Jr)rHc%r3fdAr7FErZwh1h3E`N2JLFaMR0Ume#9gGSETg-MHvsT`;H6j0eL$Wes z!X#Pe%m+bkfeDxVqW5Y~e0P7x8CJpKL- zsBPW*mNjaf+PlDg>Ez$c3^9-LE2d_|<$gF^wjlo6N}Gf7w(RYfq&NKa+OKIF^6PA| zy^!b+Wxh>LKYppL3Xb-^zJU3Uq4wR(RnHrRA5DCJ)Bo{7c3F1zg%8>It-O}ctNeU6 z-S77P@A^CsT-Lnci#q4}d}&&q`1D}+&sO?b0^C*ZzOotuTOIhCCM@3aE%fM|QHO{Q~zs6zzx#H#i-ZH0?ZTzP`eRDgq(|Yg!Ly!JlPTk$q#D3%4 z*}?}_jejC`UAxkJduPD?2*%&pTMjH%yb-^G>y3U0>o<16$CbXy4u4!3+9sdl+4am| zw#(*v71*yG4)xxWaH+1@oFn=#kdvPEa6;G$>e z&dq)P?A)cyL&|9jty3jRx6C-}pnp2$rSPQvkIq*%8Jw%#^3=or?fx~nDjBoO@@7OI z7nFD*>g2#&l(|9GzJYCvl!|zBj8=fjOP2|o6ym~6?4ugLAIm$Ok*0UA?c%ZrH_HSz zP5Q`~^i_I#;Mbe?+rGFc&7R?rFR&xr-?_->-6dAv6CZkJ)`=~Qd={RspZao1#lz_a ztXx&UA6~lL^#03g$MgAO6Th}4-Fd838i%|8zR3_9 zsrPu@vv&{dj@X{9omSneT~vSmZ&S3ATaf#$lMHD#>(ef+O^H2S7d=Vv&jD-a?Gyjc z{{7_t^Xu#H@mHyo2+e0#H$1uNjqoJf`De9$y?p;$&U|LMA+9|pQ!YA+b5sD5(2oh9H)=edpSy5B<$yW4BUpVfP(|FF-V_g^6A z>^Z&kNgLmC&)n)Y{ho9CWCJ;|Cw~+c)xUqtSNMO?hCeb6bDrIbSZ6tF{mOK~jVm+W zCCFUa64sEzHZ|Yq+#!h~;}Sy~pX*1=9j=H6W(ji&f1UlM>lXWy*OksnV$7BG={znS zaw30Tf0Ym{pUL{9{Z0ta3y<{$Jw^+!CZ5dIdS>SOIh^TctoT*7KfP-g@b<*HZQskz zckr9&A}71sJOy)NJ5Q%cZg}RDUSwb8cj#J8n(QYIy)R$;H+CG!>zV&H?c!$bmIZBGG?dFDW^?8=Nt|kATrTe(?MAV!;Vy6SQMxHR1dv>+amaQvOZpkn&&Xt+;Nz7$$vTTO5v(N1t zd%SM1(0;Znc|q2f>y4`zyX>ERx@wrzz~^HqU0|B2)3tI=)n`ImPy7yhWyWRKG~;Piqcqdjry5}k z?72)OlRqePFS&O95mWC8{>&&o$CJk!Cg=&g_tVU?^JI0&uDf-Zbt8L~#Y2g+iv!PP z8hC55PMm%+(T-> zlJUz-{J+PPv-bXd`Wefw{R8T!()>p zA3QjdCSEIkPWRIPdo^t-Ufm}PC&f-Q7kzG)uqBW8LtfK$-6qexMXXFEvy)kBM75KC zDslX}EyR2$-rjhp`gNX*S$g_yb(NvB4BL)BxaP$r>oeo&P4T)ZH_A%SycS+@`ht05 ze&b84?wmjCtJeGehTbFo9rH79Pq%FJVw2kKWqCnA?33nX@#)H>$DY%@ zXyh^Nm_TOK>xA8Xe|pa??tWRaboPnAR=XZvoN9HVH(T!6V>yd+-}1EX9`Q;zxs@+j z-u%+@U$;LMm#POv39($6;WZ&aWZvsX&2F+g=ilRe&-q=i^g!&xo!2b>Slrz?-%hRi z0bfnn(lb)+H*d^-VyANK=*&~an)~~Be*cQxhrACCUbE;aHhUZYhxbO`SD66) zM4pwLF%uFtotfRi^X!M0#mnkfY13c%f2iJa|AX=BdVi-`{ioh@eyG0te(!Iax|4j4 zJ3Ny_9y5Jux0)mQ#NwCeOMYv?_s2Zy&(G1@f3NzrXv(u7Uf%uJ{p#PdeX9;@S$px= zs=D)C!h4!Fevylg-VnR$Z-h^}m|?&o0m+E=nB@;Fw;j+~{v@s>?BLv%8*g|E@)bD* zOs-X=9$UIeDEfTdw{0wfu5$~$*DFlb+$^j+_w!GQlk3lKFIjge>$)pE~w?Q9aec9u_MUxmqSGYy>!7QND^?tNykdOXE* zHkaGK9mz{4eh6A(F=wvd(@u_=;i=Cgj|)BIBc7$FA3W;Y z_emmt&z3X0TI@b?+s*HP7~Jtx=90h>`{XA!xl;nRbcq|(6z-_$7Sfyl-E^;Yc*s-U z88xxKd^2>zU$wfbzEYgA!msO(QJA&&`u|Qdy&X~#rg`nD@A$Tq_f)XEK~wMCd&7#k)4Y=cqhEFA zPl&MU$TwBn@O9&M&mV7(%T@3GvUj`wp_%`rY=6uMT5za&?$L-fg6|d_;+fLv%oWO? z6jQ2nEPjTc{NjlFTNT!d=A01DyBxfC)3r(YDJTA(Oj7Jz*POE3jA?@C&nW3!rdTU` zhKGu|Uco${LZ7jO$~reiPPLL^Z$6xS=`9la}g_ln@&Z}mb5Kv(k^^& z+jH}xQ$5SMZ|YNjeQeN5^nLzYIyFHx((?bz3WMzo1w5Cx1srSsRr#GseK}`sZ?~57 ziMUrTZ3(41sbS&ARr{R3PT9FmTriwXsV;hl-hmz!y`GobMa5_3J_yg$)Z6mdE!=Q< z+l(KrjE=tL*A*w!-8FjBbAOWe;j~G8y$>_|xRa9|jj}Q$gU$#>91)wdLtFfy@`EE2 zgS-Frw+1+`RacJKc5UCYyF$+u+lebC$S;zaBJJ(a(|&EDP}$#T&0zXG@KwnMIm z4{a~Fq$S&Wx@uL@->)HVO*6T#h~F|{o3rhJZ0H&3!mX?4O$|HivO0bKQ;RdM>w2S) zH?9u})?qPy(9hSDZ77^`)s1VGLXS`{%dSl8P=WgnV&{~8?AWn~jbkpybie7r{tPLn z(u=L$Fga|{HaRB1s_M#d+IrK+Il6*2$NxXwd~!F-X2;wOGg3Xdc;xoHTkJ1u!+uh4 zPC+P>7vrV8m#?b-KjQbc4>PaYvgz&`-W6`a;pgVxx_CE%K_pJvk3ZEfua7&(x4P-} zS=&_+(yzKFDD5?#C(WD^vcS;iAx~E4(_azc>N{;MvJEC3OXP7sm%GKmPM;+&Cta^H z-EjZ(vP-=VDW)rYmlp?ra;n`G-`^;Ft>zTRM(yOsTe>ZGx^Ps-&CjXze6rPTbu6dy zVGhG*+3evpmQ&8Cut{0F_^61yI1|YBHqcaQ>*mQ`Q5&n0+9NhETlMyL)?@W~*8hHN zmba^Yv-9!CTffbjEkFC z=Wg5E)OPaFvVwhXOK-Q#)mopM#yK-ia_0H1b;mwmS9(5c^&&~pj)z-QIucapeEd>3 z>1O?``Rvx$DtAqN%h@fVvpa-yg{`{Ip-A~+&iVKFk5}q6yY4XBH{+K`?RqP%_P)aH z1+7sPoAb^b%V)V1HR0}-jF^bFg5(c5xl_Y=3~Wyw5&H6$z%9ka>`V?+CLaRsaDZi z8dme$U%%{q=`3rn`~5a%Mf1X(rxoP(_i)WQ)ZFz|*t2WqhdOi4sL9X85C67VDjzX@ zb}&>yAtox{wpCCp;If@Oye%FE!kqX zYC**73qAMxx{n3Ou>7`532S{76RtYBkN`zV?pV>DF^h@^gT-?(%1Eju|BBn4aL)YJQybN#tJ8`QL1n-t6y;RvWV}&E56t@_vO!`gXOVfAwO299?eT*6kb>{J7BF^qsN( zoWg9YWYbyC_G|qW{pr1}V2zlNJ^S_8tu^zXN3?lOyw`9q?bn5cnf|@1ul7AXEU&gd zE$q$KS3eh@{(7hN^r!y;w%?CTt>SC5+P&)aPSMvpxy6c2uTN_URObe6{b ztzot87t+5RD5_--^j~TfTrP9ue8kdy)vI1f3*6Xi7&1fa%*I}UFR|-Nd%or|UhKGL zwZ_16Le+v*8y8781zdEq?y{ZuqIy+Aw&aQF=eSdUE_-QvE&IY@CZB09mOolrnSXWX z7p_$^o=8WOKTh4>z36?n%&i>7__s!`_sx$sZuVKNqgtD~`HP3(+3kxX+I`-~9M9rP z`B@qgUhSFvNxkZqq#BE;e!QAiZLxvXiV!aM`*SxJG#(3J2zY<5S$`=HZ?IadLhgF* zo7X*~Uw*wVF8}*ta`*cA8)k{EUAE@rser~)vkxilTNdP)`-FAJk}bQxRGE2;g^M5a zRpZ^aB&2WWBX`4MvsJy!`ENM3x86Q3`!MgpyGL?Q<~^AATx^HDw$v`xAOAkR{`9fp zT*|@Y8I$IyS!B z5#RsZIaTsz&-&hbE5xh~m@^pGr|>Up=!yPx`IkptxZ(EGlkTr)=R0{v(fgmq-Cf&e z?7lXsUjFW`wKH~~opk=vTH~X4B)$JNm%J{t+IXa>Kl+pYh3Z2Yy}KFlu+^S% z;^$WNmAAgBPup|GM^S(6T!wQ_aT%KfuTC+WTGN?(Ytk2^UB3FO?B1=qwe4?t|6{w_ zO`%VZO;jv6^UQjE4}E`y-Yrq1!s>sJx|Nn@24QK zr2ChF!-s=On`9?#=3H1+dd17|tuKHyh9qGa)tG9Bjl>OP$;&EyxXXU~BFOP=q zxjHNV9YbQZg=#eS%wFLK%wO^s-kyBB%;^4&q6b-}8nIl)n@+zd({tlIxPV`AYh;Q< z*^GoU#v;`_=PX-t?n0o%io*xi?qYZ-#kAY*%bjJD9ZllO*Ct*hL5Gi&3IP5Wz1OOGxLIdyy5zMq@*@9och@qwG&?)Q12_Jf=DeySAi zDg9{wTx)TVB3CEV=rJRq^KC*Ph%t zFMs#>Yp=UU74lcVuJ4h4{%ptVo#zv@-z-?WVeu|ewJvUDVNKpw=IR?Q%{D&U@$k~w zjdF%B$_zKT-_m%$I%`VoC+!Owho#l~)@RJ%e2{nM%$r+#rw0n`*;99aYVmRZ7~X32 zwL2G2@Yuhh^3SZ-g;M|Ww}ok~3{w9%`Q#xz_LxZ_t&>8+E?inRc}_|Hw7<5qH|+Ru z$^75Dqv!YdZQ8av&MI&7_OiQwZr1UT`L=&=+426mxuUQ2 z-z2ql^OD!>Z>YL2!zy5^_rC2#y!NHkbuSGkhOxS?d+YeHKhoEU_1in4e^ZjDR=8P- zZ`uEON0r+jR=e=3-1AGO$*b@x7zVehaw$H|w!N=v^Ir=XTDY6 z-?BdQCBKU8-YBuyW83Rbn#I+d?^oR1`$zKmf=eeX+Iw6>E?p4ku3~!ZmA~k*m+a}6 zkz4Y2L~xWJ_*k&mjEO65pR+%E)78lEexag>bKBi6w)B??DJ)ji+TCp-;Pxk)Xg%k>h|xY=cg6z^}kc--tVX;#b5a(SbCep`OQfI z;(x5?hu+nkyZD!WXvfcYA)9&ENSJZXy3}^%_F17tlWuM~qRP22#5y#pW~oo=@&xM){Oc;*Tdm;G}tox9ZD8XzzE#=Jx@=+}>ezs83)PN@?9**$Gq zP}O9sr`olPQa+eV*ZnJY-aP-0y5){9-EHD07CwA&n={s4GR;E5=2=R?oXOvICYY;D z-T7eWjW4_ter3(Qs#oadz4q#wYr3gVH!LZ>rl)K5^VYTvedkx@E)%<5sdvDeQGNc( z4;twc<83{+F6S?9<>)bzUnX?@2-n2CjF%o0zBTyygoqtv3lI?e7I)>+;i4Xf>kh}I zADrw7=Cluc(Q)`DAIFn^<4Su`=EsfNVb5Y$Ij5-w?D(WxXw@Nn_hretz;iQSZn?#& z)@bp-p}XkZ(g%#+b=$dr1()y~G?@H2HG6Nf@5&h#?FS!6J=*^BY0;HFgU{Nx9&WuA zAMW}oX2$Uhxmyp6z31mXPjC6@RdIg()~KjI;o^3?m7ciI*s5pi%ANjG@+jZ(Cq+g_ zI>Rm4j>>8$eTi8pTy`u_UaC_`l9PGCg2x@NtpBcf&rx-z*7Uf-UsK<5Bf}0UqazI~ zxX!pFAH6d}_5C$>ftcHq?z5=y@@#K9IPbN@0ndVaH#5f33n; z+q~-%bpJ-{CO++adtdg8W%<31?@G}!ht{oHmsB*K+c<%J(_HN@ zPWN9rNl%K@~BcReKG{;o!TSDqyoZ)7qm$B3tF zR@85ts#jX)vw4~K{LIQ%PH$|FDxG_>|El1nc9pX>FXz;KdzZ_*kT-YXw2D)Vcl#$LD82Y<+Hys&th)E|L;f%z)C4ledTQzHN3_4?9X+jc)~ON;(}=5gb# zdl}iw&h5RvXy@ZY6N`RIrCooPXuIOM)sEhngR38O-%fhqW}Fz}+R!&sBW=IgkptFp zU7|Tczf!ZeOl(S7z2xw#B!|h1HUw)v-|DZIZ4L7uPR6_LuH^g}MbEbCrJ3V@P?w`iYsS_?@f+*Ec8} z@3!Q7cx;x0%TLDHi30PvE>u5Q>9kt@vqEN@#htWAs)`k>1Rk!QA9%<;{?QHYInDY% z7Myq8Jw0SnUvcjpHY;bv=(KfeeE;0id5VtYyx2Lh@uJ@)jnxbD(f*HlJbo zDUUT5X0_eQb~tnp}Ml?L7oEh)ftm2AF3w>WM7bqs{iEla{AKuw)G1`vkPuy-+T7o$k^QIis1|X zveqwKf6sn>?QY46=MM4tOYYnMJsYK;oy}Raqh)vI+;!}1Yeh?=BpUVxF8LX~JS4f) zR@lKmG1O|$A}{xiUXIcI&&-{sCh_D+XuU5k{kk@`;oPj(+r(s?dM@UOX5{Wat~K@A znxKb!!(T>guP*s@#PoZwtks^#7Aeuz^0gPk_10Z@n5?{av0~Kxw`=S;kFR_`NkRRb z>(@C=OKr-s776G(xw8v9{O#am?-uBpFlGJ^*S*mv*s59eEK&?#-xYuHO(GAGW}MkUCei2m|md&~uE-5G&94f>=@4*W>ARNs7^*Gb2-jxWiXq2{ES^U@`b z>aks~YhMehS4Es-ed#jymPbFY-`ktt{~LXmOUMhoe(S@{M5@$xs?Dm) z?vFLU-AJy!v)lF^?}m-M%Wlf`aGE-3@HGm^Fe$PKsr1S^c^Yx5@-98TbLVuGCu$Fu zO)k?vTm0w!)_#+DlG2lY*WCa7N4}!Z@22~$+Vxw%MZM?#Zgu3)2d+EodLtZSxz^s& zVcO5K;uS+#Afx89Or}}0Pu@yUmhjM=)M;d>%XpTTt>No!u?wF}ZmQb#r~4c*3wdeV z$8?b)RyfTsM~3hCp2YW4Pq*uHUSpkJ`mCihctUYpweaQnLMd-6{O zl%+1MeYkJg!CkJauj^$>q+_I7Hqo#vPxcSt0O{go|) zXU3co%do{B*`e1t-1mfC4^ZnaoYK`Nuw}{N-tazw3Cz!(>h7%g=ygGJ$2QSN4rjA2 zJXSNd{1BOJ%(1PPb4^K>uUI2z=oA(s(_p(*!lCE3ZtDtgUh(IWAlILW8W)yNf{*uz zdDJ&9dcWL0boo2ZP0JKsE$7pd|HGj|*1m}KM#-^n8P+Y2cOzHL>;VfiUCbCa($1!>RQ@o<-F zv))>_#ihJ@JKwdbPszRedEboX?x+7rWu2+saHerq>N3LmI(NonDx(z@X|64oy!$v&(QGSDp-3#lgKlsGjVf647%5D zm?OT3Wy(@9ixsa9d{c0m;(Je1RHtpzm3v3$wF`Vm&WvsC)fU!sXLP-tZ!N#mcL)FF zhDpA1;d?@T7j;gKt}5Fal54TA(cSP~$1%xkON<}Z>nwiK^T#sly?aRK_YY$6zxP?r z4GUW%dM0BpmrkMoq0A3w-@lyxN_t`1UsJbEImf8I3wpS#bfp%mJ}z_rcOX(J-)P@m z|BCO&Za@E7>Zto`;j52c!3&G+l0I_=`-bSUewq+>G%trSC7enx$UaO0v>%oY*e3Iv}nKlEcfx`?VmSI*xtu{c4kNZy}#S}S7-J*-7}eI z&QbZ-BGjcyxIl95vH6Rxnzf!h!FQRLSJ-#+nT8EdT%(TZr!T4~dFXHd`PK0on{RWy zmHoQSeQMIhH-+16KCTL?3H^CKd}jK^IY*nD<8K-rG~6jR|Nk4AXE!$&ugLtj*KSo~ z#mUYM{9fCP{yv>sR=~KFEAC^hY$fNFAoEj87FE@B2y-lyjDEQN^b1i-)%@wHOIs!x z*?FGyy3P9go^wHXZPz4=xxd_Qm+V`WS-E!Bnbo{Ym`&G*zMp>G&1nVCh5(kACz!6K z{5`X0k((*=`UC!}BON^Fyp^2!ck!<$Q;ULv7EKD;Ww5?5E3LQbeUtaya{dPXw;}y6 zXO?<@TD?Bx!_imUJ~sW@mGN|uy`Pxtyr2W!&#o_+wRzdI>t%NPxAC9Kmn`#s%T^V1 zQvAvHCa>n6_zRNrf~*hs^aY>H?@Qp?SaGGUO`$6Jt9RdX)h3M;@+*VnR1;o= zvAwAHzB~G)$C9L)d9u&B=Dd@&%a^NP_xoqL^9Kh0$UiPe`~_?lew29DV#u35P5PKm z!I|zuGgNMUT*}+WW9qg!ZQ_Uir#>Q!BK?vNeNEnceA%CNb^`^gUy^!n-0B|8; z`jYv@?S6If?HlRJ@6YBwuUq-&{LSmn7O(wY^J#L1=BnRZtE#`>K2<;2OqgTcW2P+2 zuLhxW*n@J)Cso9+P+H6C{p*Ok?UWPx{mFq-8>Y`X|3sFPBY{)xnAp)XT9p#3eO9&1Zw`u`$+OA+w*8rS=g(KyoN_exeG;0umVdp+w8{$; zjW=^1cv!UNu;|@=55q!jl{d{foaY$#WW|ix8$?Ww&dHs9$3$Rvz_d5bt1r#ZD!%;S zp+IQ)619o5Dov8EztoAY{{P$V>VYd}1&`d-*=}9w{{3%v`D)kYn->elZF&{4Iq|RJ z(<0TSF?AVx=cSj1skw{geTop#G0_Vfk8$| z%_@E63zeXao27b+&v`zU5tC58bF@cwf;6|#jv22@6_{^E1iCKNW=~%J;Z4xCprpN1 zU8?}xyBvYQx11Eemb`~AT%H%bL!82RyLQ%?o&#%w5&(|$*GD|j8Q$O%U-D>q7)5Zjq zsQU^6+_g5G{Rs~ZqjTqF&9@g>x7PTtaJ>;@IM=_$th@Db=m{5Xqce z;dPsZ?SDPrmlALF-rLoFP0icsA9f|Rm;0~yU174$bJ?N0*SS8{vHB}Ja%o36N1U{f z-?ik|3oZ{=mf)?6cLmKfs8D<3_G5m`_A5gFBWo6{{B9|~a!%}*1;1n#f8Nu4^7~U0 zwp~#NmtSJE%D#I3nI_w_dRd<*e>XF?f0kU9tzTv}^|REE_fjkBvgA59e3{NAG-2OY zpRavo)3}%{raTn9zD{e=1HQX_iSMojbT!m`cbKz(ub$hojWhe=r*>*&v3?Z%&&l~Yql-zX0v9B%n6Y^zi_#6;t;_Gh+sD-%%<1m>Ja_c- z_xl{GjN2*}C>v?X_)j5}nnF7oMDnm6&s1=A_uUJ1@2*1azi% zI6it~aZRE2d9ZCE$D|dUQ}0wBmrH6trkZ%~XoR$1w z_SNZ_sm0?xttmFrjc=nAB98>MzIwj+>VyD=8>g?%^n1lRMSA^I7x8!9u{-p4sje)O zDY%w1>8erQ68FOorA)H6YcJk$y1Aa|zfv9z3GmdvPS#O^~-%F*B0_F+bsC#V$18u{!LGd zeC6Fvxc{DVT|G|T^X~kt&W}o5U1@P4b!v-pPi#N;c;|iNH#4ISP2Ix(@MO*s*5&d) z_efs)oaVtFznM>c-~GokPqN3B@AGYXm9cvMCAGNHEv7MBd{=C0ioJI`pnXJ_p;CF>{+i=E4NPT z3N!wamc6yh>g=i$rzZ1?gi330vo*~SEr0J2Qp&SxzsAaiQ4JcrCS}`Ru68r!`f%q< zSmm9Bi&<}c9>2Shp10m~W{i>4!MQJ&m`7E=$TrW(`sg3eVqf)3T+Qvh%WVFokJJw) z@+?2L`4h*FsdIbE@@00W-4@w-z{4PVZ^HYzV)e1cu2rmGuLWyWbp*UCT*+|h>4F^j z8>{9Duq192&d7+gSt=e8{WYcGo3X+st5~`B>};8*m4tSxePP^qtNg+gqplUjSJ>Hd z=l>Ob>w4u#y_xVmm$X~AF1wVTiKtByKll0LDVzHujGf1oos+M{`rP9@Kj&lU(seey zzWIl|EdJk|6S>cG%~JPl*OLo-PH#?4y<@obC*NHDzu{_42NQZH74N=SarS>? z<{e6E!VGLS+MLV&MLDceexf=15red!sM(VZ0_HcOIHEr+Pro$TVA9+zJSiF*9yT9r z*zvN+;pjpsfr3s`zON#8>^aOOZu4HYnWts?W0{%6f<-^NQ$FX+dfBR!^Uig4-2Hv$ zR$MpW?YVnqlUVlD-EH=tdRcx=Y%uj#e;zi6r+Htl;R{K1UCF73H}9(r;ksIp!*qJ) zSv9p2GkRpQr_If)SJ3(&SGlBmapba>r_UC>*6F-|-rL?`3iEP9`y8{)9ELiFFD(A; zqgJY#$Q)Oibvf&2yRTWzu?&lvcDFm{pL{N@61$#hUa+)eTIt$~ zMJLLH)}IsE@%z|k-v=w}O7zhywNP(Przu>U zAMG#>J^iY$`!3_()90P%>|+0Qy=1+@)QM~|QH+`X!m1`Y!5YFxPKjMpiC$KD*=@zQ z-u&99H-)RBwmavWN$>bIaoJPrKx4`0_g&{t_~GvH{?%jE`<$D5`c6HQu6QZ#|L@O+ zb*BohbY$2*=ggJ()p_K8!nCQ<{*%AkIW2K?S$Zz;48MuUR>|waM~Wo8AADt1+Oum%J}?1jfB7c*8u;!8x&v8c&ZS{^q}&9OS096+jBy) z_UgRc6p+2HsRvs>GIs|;_`snhlT1VN6xE#TM#d* zZdW7oL1YcFIN_iT;wWYrJaSq_10E>1k%aHb2M9%5>Z3zh5NYEsu@Zrn$|@{_641 zhD;Wco(y|=ZiuiZ$-L-0?DnGax2xLg^%k>Twf>cgu3gA@Q+9HggIwm@RSV=gl6s@e z-dq3k+`Vbe8y~wXzYh01aE6#ZDlh!#`QuN|WB2*BGOZQO=e{jk5WdfN-SX@5rl+;1 zdHgAh+ZAJWpJU~R%;!O$3a@Ks2Ua>vP!YcMdsUpOrv*&a#Cv zD+tveQoJo2tD!x)*t%0rvv|TB`KYNKQ%+iW|JH7vboC|ArRyn&{hw@D==WQ6?py6e zj_ZT>{S!6{s_SEVwLGVet6!d}sH^7HbIH620T$0l$;g*6s*BuH8^zW4smw0_bgAg( zp62OO^c|iqsubFPSVw>QkGW|xS0x;tu=j6d2zM!G=o;k+kB>DIe17IV>WpwzTmFp2 zW!j-9SESCH&(kcJ#uCTk#Ts6$6v$&Pl;tBoZ-La|f?F$osWfdh@MZXP@c$gGEeCp7 zCSP8%{O6M%lg=%6TeqpTiv*bcJZL2R#rx0e$rmQP%lGlAajxXr>-=rU)=fVPMGt@8 zACUKbWAg5)g)Y6HE=?7xm!Efg{ez|T8t(rJpI({a@#S3U{T+Ns^AyA;Db+}yUh(yc zT9$OFwoRP#;P>r^|BB@bJx1gNjuf+9ldgnf(27)>|SPP?Q3s$lssQ& zJN-!7pZ22OImeVN=KOPrtu?xO^Xl#E_6A!LK2BPCdfNJk?RAIU?i`EWmUnyK<4dRY zzWrkV%U*pYB=Mnw9OLTp`SOexPYNCgQ4`#6^Y-$(RJG*+Z=XmyFALN;HbJn-f5U|r z9%+&{^GcT(Wm?YeVf*`}?W$j%$DhmptQTC5-!;ovq9r=!j?|Xq$=526ti0Q!7khqZ zo*)lf-rG2jPZJMF)cpAoxb}16@^6>#*UQvPx&C_c{lkr2hrXYFkpE1%MeP5pZ4Vg2 zMDBg~UuC#2#$!H9xk%Cj$JIJ%lY@84zb#qiKKbUN8n>_EipM*D&-JTPxBJ9awfxKT zix-Qhd{S8Ri?P6fj-{c(!wo5r)%d>RfxL?&!p?GEKmFFS$El#=4lYY!yCgj?6 z#6PewVWn@wB5+7XDYov~Z30li;O`u9$QLKM7{) zh$&p-s@BNGlOwi`h2e#jP|I&^K54UA*PLp(R(IcQ{HY?d(eKRnPn5-z`7txY=yyhX)r` z`FXC}E1aD=(eb+2%j|cZrq!wWkLUD-cDh=vvo+Yg(N<{EDks^_gKctejXg`uolI-{ zl}f(p{@Q;&EBluD*?)&7JU^0KtS8xV`)2X`g`2NfeqlXQpmtESqtZ!tq1NQKItK2; zR`&vhKmV9q*Y4OH(3;P(EbzdhwF{Q5c376$W7E-Bu;q%;zG+dnmJ6wDm@?P>`)8Yn z)(m1hz9%?$|7H7SJ}}t?>>WJoMAxsNK>wC3TkdPS z92eDjE_GtK6{<9ClT)m=o%uAb&mStMvJ|l0c@vl6r0mfd(khV@buRrz&gK74el1dU zUHo5)`N+{%%x~93`2PIZJxB5W&sT>o`7vC-p4gNb?|ydSvq4Vc;MV||`EZZ4n6S3-JLZsArt0>u78|tFC^YnQ_7Pt(I#zARVa6> z>a%i-8e6eWy~e#?|4fpQ`W)guZHoHYrp|+pPqF1}uUxqG!fe5%>3bS)?TWa5$1!6U zGxGGFP2O;`gi}C|KpWGv$q&(T<*P8 zamH~lrOZrpT{!K z^6Ba-+f$rh9`AlBEWEq?{l3@h?xtVAuxQD3;||LYv#$!*U-NXEwT%C7-|e683mdmC zYUtb*F+2Euz)^!OKVux+wQkf@^p#9Kb|-GbHl_^b1u;*A1YS?*Y*yYkZO6UsQBJ>8Nkq`8<}xtnpMZIFh!}Rib=Yn&%Ye}Yq^hGdggiemOnx|OLi=rX&WKc$&vh! zBlA%cySbiJarGf_lOpcSC;N2ro@CW;F}t_c?32vK3-{Q1ZN$yGSsJF<`_4Y&^OdRM zmbR$WF8duDcfQPhJN>f!m0K_BuirSOAHF}nSlhfNA$z~&&1*WQn>X_EH1qwB)K1&2>roU4@5lK%JsXVdik>x5QZtYgEgfD4gWH!>EWbTE#`5Z_*W@$7k5_HF`n>%*`?W7$Y!`3&v46?s%K2RP?Mk~j z&(B(%a!tkE<(5|4u)W$fa%>{~x?j!ouOTQNS9`i;S_{s+}wfB0)%{%rQIy!)PK z1?a7O>7Z|^H#hKp>HqatzW>}cC+>Lg>wh(~|J+}ZZ#2E|zT(%rPG^^g1w3YPyucP< zWDu>ZC7Kc3RAC=Fy+J{dopImM81pMxeAiZOV>!q)bIrfcE`bbBE(dCreG#ZRr?+PH zw~_;y{^oUSouB%BSt+5YH`(g6j==F((oxS3%Uo6#RW3{ld?nzYdTW)qZu@TUB~C_+ zpM%uaIjzza;%3@6FrLcDOBO{_fv|@;|qZPiZ?Yxb~`N z?7M^ejvQF^?TYK|H!EYy>t71Tw(G@S(s{9EdUoVzQEl0I);EvOpL=6}z5S`|xpNYX zymQmV-^ic3Qu=;h#qQefrfUb^nyqcTRp9IXXmW03p4;31_P$~#eJ6@P+HiL2`6;&r zUep$H|BCtV()6Q#3+v5p^M^NQ`kn}z6>#_TiHUo8%%^RLK4r(6J&A>LMvn9;oikxY zGA*ya27fbqGx^Mk_soZ5^ft0FE$6H*+}7Pz-_UjV;VI_>jcYy~zMWgPHg>gQJ#UFZ z+oFbZVugzGoo{OHic0eCet1RJO?jc#^K;Ma_CLAwdaGN1XxUM=$93IuCpR7WU?p}_ z?A`gO88bAZ7X8|Gr+1-Z;kV=AdOOTsbUit@xW`qlp#5aHokM)Q=(3l8cTTNasT?Dp z`)0$bZL?f*+pkMXX7Oaq39I{mNc3*+zJ=$eoxAp7-#^7&$KGZ+XxMbVouItqT0s3~ zjSpK*8+$iu2rmtu7r)N@^p&d1p|5=BY`p(ixu-e;=GF82;fFtG2yev<%nXj`rj$N?nG>Cb>@65BYcCRfXH6H6HmN zkFzK1-F#)3^|fmHllR&8UasL%eAKcs>~6-+Yg4p-RfS8uexp~;YkOtC{++Ju^b^-_ z?96&tckk7emTYmCIrsW*x%B#OD>HF>eOPu!4R?J ztuuEC?@!yMeC1qXp+N$RDrl5bDD*k1x+>kGl{y1#m2Zg$-c+L9oq&KU6 z%N^nDo6ey2a8=MhyM-S(|Geo8`sdyGN7(7%=^u}ZJO3>A{;6cQN^Yi>-q*WJ|J?m} z$h$%+r}gbo6|pw%oskLIZx3ybUmx*8=2-c(t&go`E1Y!R+|=_rdSR6>Lqg$etD5gO ze1E)I^|->xrr@ruJahhib-TuVYq^8l_wy8rp5OM&UiX-A#s(&rOGjf&%Eo|5^MedPV+N1YDL%O)<6 z5J^2$mgl|f=>jvYZqL9{1A)f6_6nZUssEYRl)HN-tUo)^kI^WKVfnU+1&TF}d%ANo z=Lju7yz*53%@5ZF6!aVnCSKNTDhldtGSjY`acW6{+Nl!(7d^~o`mrvn%=)|g>V?Y% z+_F2DE-MJ2 zKRY*P-L{*nW>3zG&eyws|26m3nOmZQV=w4;T)nzz!Uc(sYwyK5#5nFfzUJ!fyW6Ch z{diw3mYi%och$DD^K7eUEq1A|i*#mB-&i2ad-_xB(%!cP_wMbuWMZ&jja&ca_g2>| z%To6L^bPs_sQbNbE7Pg_bG9sHvz*$0#jKKrZEL8z(!0Lo4}o{fo*xfh*{`lX=Y{|L zHEXvoeeZYk)oZ8X)@SWPOuq^vip;Mr`gi;rCX>Z;W zy$gQt`=86}J(U;xB(E=eYyA=CC!0V1dG7V|^vP>4R6RTL_gc=A_j|-RC4L@*qqIM3 zxIFXaDmiZ9bO)(^&Yw}HV!Rg`vmd%GlxDnJXy+Pom&1m4vcN5m%$&09?R^J~wsRfO zo*y4B6}?lhIiGjxr`IiqLOC4Rj`PJ;ho*iIyY~K|@Nq{bn+oN+s#>Q0n;UQU-|rC4 z(PcEg{kDRGyY;-3^r!g>FPgurGZcMb@vAmsWOQ!*B+DG6J7^AGa#}_p>wc z>t$_P=$6zw&qkTiZ!5!<%&R}L5^CHwD8+bedHirYpF_>F0}T7WY1s&r_uk<-{OjA= ziYs!tx-$C(lQwLv$gtBDdsoH7GQZuvFMn%Xn{e&B%|BR;w~D*1i$5cICoX)O>h;ap z=aWAOyXPO2~5nX8SguzgX{EGdJ(<0UNf$bElr3 zil3NzZ>{w`+gopV%F`~)pUQvrwuJnymbgz}3M^*w@Z0Z|sCU`L&Q^Ef{{MG7BX6#$ z{_xZ>-22&b;rlMW-|oqOGm3ZGt|kBR@;A1U2*dQTeC0$z$%x8EAbaS1arM6>RLzuVdovl00doBFo z`geP3$BMJ3G&_DO$CaA732#&0{c2)Gp*+T_fofsR<8fsvG!T_B)`?xedUFfFNSmdwC&zcU4C{?^ch8yraCc$Sx4%fPc8p>cgrLGS!cw)NG+<@ znBjBq)6idLhsDZ<*~d^7j|6V{L$y)yDtqUsf_`z zxTbZ-DKD4RczfcOz`ykFtjmkyCOdli>KDR>jnN}Uhe)ScSYpS)t^G2 zajXj4x9U%Ci1CM=a*8`b#F~~eTJi?fFYH>jiN%v)WmgYliUk{ou_cqY_OZ_@Q$%Yl z{}u|JZNA;6`BYM9mt#Vf>L2zafdU5(9{Lo>_mz9{Oq>3tZ<{oZ?DG_5G5qEmGC|d1 z`jZ>x+Wxs=JCe5^3~rY__qOk||6jWuk3S#2oWO97+40j9x0F}ul7YXPI?Ka$+CG>% z<9b(1LzC7Gmk%EcAOE!05Rx#uaoD4)?$7eAKNsIDkuYak9{OM4=j6?szGXdo68d6q zb@Td*`hH(Nec4f&R6eE7$m(M=>z8G$r~LUATd(_kul#H6^B33E{VwcQuWH`WYu9Dh zHAC1|{leFB`(krht7UiUd;T5m>P(+z%y<2W%=OB1ETuZl_66ppwMVtrsqwuo47HK> zdKR3@o;YETbx8Sg&r+cmAtAR|4(w2mQ$JFx=j{}5;IgJvz{20sN0ZL3$&1)^Cukqn zbyv|f{qG#6G;CRZ#A(ULq~Ie_B&?mE&6z{ zx%>X^(vJt#oAtJ>)GC==`ekdfzV`mDbrP(8^0KzIRbMoA?cet6^VO|SF4X^PZN9#v z$x*zvxcvS^`S^C7$F+BVZJ%HF>+N!D#h1zRc3GX@^7DLSb&mJaV=`2aF9v+x?L08nx~r-;I6FvP zFIu;1kx%4X@F=b}VEt~*`! z=hxPEUv_1^zH=AN}cJHwh`#0^Z{wL?JVlv}u?8LrJ>vzoB6W491 z)*61SZB1<7ana@GPX+s3?)>(-TKaB^-N)YS`BuL-EZF}&&Ub<9`&-wnGvyUaD6 zz}L6I-PUpMwp)uYv#!4DxL5Dq8dDZExj5@pm+$V+JO9t^{MEJIE+?lS{! zz0Fzr#Zjjfb2rS=Ih3JVV-3mwK#RE6QjZ3hswgfuFH)aQR$Q(>FTv<8p3%&p#F4 zpWk7kvc4?x5&vFeu@6xe%IQCsZ2Bx1d`5=5BK~Ki{gel5_g*~4K0l-9%e)1feVNOp zN>=y1KgLyGGBeFHk57p;0bM(SMF)r{3sYR|4-W9lt-X5X1D?_TJg zoS2!_aWk}jZ)>X08HKGgn`C2VR#*pkZsPUR@vF+UG%|Ilc~IK9XlBFR8NI*Sk{V`w zVS2DMRg5DeKxUfJDuvwzhi^oGRukN&^d(5H@x**K<`A{+>!P#eTM9y#>1Ut#P#+bu z!)$uDo9_Qcy})-*&t7zSFUr1+UsvMh)`~>;*=Ns5)W15LBCfM1Xy?22r>2^>AL^U6 zaQ|7M)bdcJnJ3>YynBVG?rNz@+FjR(xGc`CewR}`v~FH+*ZsTVl*H;uN5oVnENV&7 z4sd!hTj8_o^zD5)yuV|!B8u0}Sidu3x%aA8Ep6eKMH??Ivga+ilE5|N-b6Vot*)=U zb7Q%ycSnh@iJHh0F5Tl1^zYA#jk|VLhTY%t^NaQ=Rc`55&WWq1nz#FHw{Yn%=kA*4 zcF=U~+OJ#rgvzHZR{vm7JmH2#`b{A}8L<=dCipnbON&^jZIKPmE&%J+HtN*asVn59Hd8HPXCsA`h7{~x{0_`n3_{YP(iu)Q3Tm7ithX)U@SZ*U@k_(JkWTQQ9AybRr7vWsP?(KC80FCA|5nq*sAJshf`Wu?xJN+xM_J zoIBxeupn#eK?djM$wqNYWx{r6Ex(kdcmMm9JF(WxzO%QVx7?yQHA>{o&eGD7n_m~7 z%?|%kq8B%3&;NbZFVtuL{QRlIamB6Mb5FLs%&x2b9vhdha6$OgS2gpPy1Ux%4!6gD z`uT@(PTS)8()+5_uOu21eRH1w`FU6JWQANZXMf-YR)=%zmNGapdL37DNV%rskabN_ z!`!0qGp9qi!aUPD!Op}$z4}Y@=SDczm)RBHzNtOq_MMW;M?}BqzxdMD>8&pFr8fQl znVjYFRyE&vo80+}{%VxB7zHw}n*8c`={~UtMy8hVUGA~<*CyJ$_+Ya?8EpmBl8t0r*D)Hi7TH})XI4V$U&GB3z&aO+wL8ZMHOsf;*ZrDv)o9chniTOt0 z+)#sFi|P+qYByGA{c7u25gdAtA!uVluw+wV0JEbygFgQW4l|Widiz-}Y!~+FY1zlK z=id^^Pm)6F`+4o(W~_Lh5r6UH^^4xmGJMnC-s!c!Wf7ijmihdRr0woz%Zb^u?r&W5 zILxE<+0i2V4ZmghFp?2K4dkNRFe2%|< z-9OtT>ND@n>Fa0A@U=JCXglq<=$?<-UuPumV~r30SN@In%g?rN-`GB>iY#5;v%~h@ z!Ly$%cFEfI%yU|Pk^9B$7ve8`ZCVcs$vCIXU(UVs;~z%GOBJryqfGfsmq>l9J8{g9 zMQ+kw1-A0^8r~B!BOzzb%mdINQ%;G#{kYf zjq4+p1Um2dXy1Fy`?gVp%YpYvl1&T#AKsw&?v~`I!?7pcdARPL;lZ^nFyP9%WeWFQ z_E`nri(r&w-aqr~l1o3f9ZTdr_Q9oTzFR?&eolVs7DkO;<;3d(4(WgTPnaxOpklt@ zg7eGJPB!mF3?0WVXDwwowU9Yz!mVb#rDvTE&g9dX;C3Z^qrsF5S(7?V{;X4;>Z`I* zZE;|?Xk)EM`&Q|t8#-2baL9d&PX$DkHX*mQ_`TLLYX&O`CNsqbJJv zapaVZw_m;G`4l!=^|+F3uZh*{{-vfm;_0qp7fl{`Y?3*gv9*4YB=cd3kM_O$+@4u1 zp7%7&szgH+^R8ZG6FzKRSR}jNnaRI6?bxF0#TB_0N3MHUDf_;5VdTX{8}rMyzNT%9JSpSFCFi$@}27U__3sK@+x($I!jai1?61dUfs|+ zxy|-+`d;I$@28qxH@gwAb@#uA`+D2;?qB`4ck0>VtV}C`Z%Ruh`(BNi5kF1V;*N3q zXLI(|OE#=Ol`+Tsc*x{0yL!cLg*@GG+jVth($mU3N9~uZ-|kQ<6#w*NmB1^5$6cnK zUzXb5_OZKGIQgE?>QtS#XARTm`(3y=CvLWoPO-9;@0wND1ACt|+udGwRqv0qTVPSt zsyj|w6&K__NQ+I|T4rCgVOrYkb)Bx(St`P>q8{oF(bY ztGzj5YI0;Zv*Kih=r3#LJ+lZqoFRDsp^@b7tS>#=R#k_^Z+&LG_EOp0%VC$_emwC) zLWrk_FKYU+t!hPc&N&>nNZDw#sC!xXYzY}O3#;GZj1R%n z7Moh#YC4m~yE;ZOC2~&G^3;f93ob5NS+jP*^6+3q9cN~_XHje9V;n^nr!EoaU%$^ySx~(v?2m>+YNI* z=bWyyk33`4F53$PZ!)d8bol($6SGe67$0g2J=|HHx7SQ4P4(Kd;C(CSIM~F=q{Wur zUHkZP{GY!cU%xWHyk)}9?1sF4_{wb;4Ghi>`-9w^{Tg558KzRd7htMU#;{t z{LfXX+f7r;brROQ&;L7dwf*J9%XX_~T>dJ>{!WS~EZ%a~zg)qYtBTe(pSo#&f5!jW zv#pmMpK?7wdWA4csX~O7RTE1o14rBMM>`_Bq8_EKOm$d%+e2lpqtJd64S_3XD+(_# zbFxi;WX=})Bb?DZdu4=o$iXNDWx0dC)-P7Ra9l2NbKzOX-7}Zi@Nam@clGxgf0@NB z{hbn$jTGh~<_I}+IAyL=L-{$jWD3lkUw zsyTm7T-rfP2l{C0Fg|N&LBR@8-pAq1>~|t8Bkc zdb+M{->rbf+V^(7UpaB##l3qcR%%>>n3;WQUEkG`_p)zdZVNthF1r^c z?fYxitQy&=Wr>}2cl|6m`&R4?Nz4}XayS~K80%^AWy6{<4dyqd8lH!Khi<5!qUd5` znjs_*7OEFGYu3HS^?>H;X=={vmzoRP?E*`d6;U#@@acw*JkR7dNe{_?zeZ&hdNv z-2L^>)jHEQmux>;B>JzdvxD`bTFL*O8&556$oO9PeCpw8-jm%*9X|@@2Ty(HX`pbM zHTt*lqiN|e?lCeS%G6W2S2u+u>=r-g}% zxcjV}aoZ)d#VonWEJ0!3G680v@Gw7i$q6^KpG;(0#8$rGqHJ@AP*m3BtNXL6yyXjf z&-cykIV)H0`X%4=?<%Xv+f9D=KHT9ow`q@CU$*F?ZS|DE^wL~!=BT=un`skc1fS|} zytz5qqhp5(ch!d-pHiH;|FTy+Z1dU~sbT)0OK#x-o18{B?Ozr$`;U8!3oV)I?9#o&w z`H}K2sDWczWoX?#TE#1g{tyTW~X6?W)!N2!RloFpNo}F#W_+*u0?v;+x zr}Bl*JMJ5(y6+NH6z85CP^ZWJ*>T1M<3bg!c`u}88XmhIX5pQ6xq(wlX5oiFozKJ9 zOlPUMa^j``+)Kr48l2L&`<<45Vf?Ep@<=yLMCisT=clHB0xI85Ihby-bWfYS)_P8l zh~E$T>;FGyzrIR7qd%kSckbqdhi(B*1`;OH_snMAySKnlg5{~T@*G!#{eQQ49`T?0 zeue+pw6B_8Jq0h4pYP|WpOUK-|Ew=4&PM3=iX@IFyy74CGsvuBd0DFUmV3eRnO?0b z5!)F)nDvRvFZ5&SOOhxJQggW?vEVg>3d179OjDi6yiGf_CUpjgiOEM)Zz%a~G|BFo zhSxvQ?Duuw?`i9=Uj1+55Fel1@odH3Iw`F(d=XKbB0O<&`_)z;6mpTD@+ zuXucQyJ<;m?Ab%_<#v3(yL)mFZ@hNx@Aubh*emVo-uV0H?f+&Jvv{U{kNvfUHS@GS z3uYZVU7X4+y6{v)W*DPV>)BO0S0&n;0$YD&#Y|GTu{G^nkNCTDDyIe4HpU!Ts>pHu zJ=6VTS1c!;^IfF^zS4W!0|NDXHapZFT%uKRcwe!)sq!5QQ)vm;6-hF;78*u= zIhgKm^WLv%;<0HBl?>hNYEF7-Mh`R(O=9@8q*17I&MCoSzcnFeCbC$vtebBs`{39L z-j1bw*^6FeDrIOf=+FEd@=%lg(W)fNK&w=*@~=z@RR^1A|Cn-9TJgmHkb@%POE1s4 zD(zW5@c{3}1xFtn+bf8cv_$(UEj)11gUgM5gMa9W7GVMtI*1hkX&fE6$oWI-y=#>7C+ZmVteM?LOYi=$>v8t&ogeAUcnG9@loZ=gI79t zcsx24`eK=xxY zj4ODqig2h%m~N5PQPwz-sT84>yn*5EhAf6{3M(4Dx(!Q24A(4`^Hj4w&S{l>N+~2= zD$6!4O8F(P%-L+yP}wxkElcM|PujMtQn&Z3Snr9~OB`y$cPO8mWwB;w6z>Uf-wcz! z^Omp0W*w0-WUu}#@0Y+E7A|k;Zdn|*x_rmh<0mENY+}uf4C9iUQT*uB*K=CVA12L} zf0s~~`P{@PEG+U^hWDF~A?0hbz7=?gXWh1pu)dwc^&)e3PRYd+M>tWM0mer`3dSexSy`LmH<+U`j2`*Lm8uBd4Bb4PfyExeCJA1w--d~(|&`*qH9 zjBngeSb3?y=icnc-XM z_^0WdMfU4$+Ur{xH-0zptBlRA+aB@Y+e))|&Dop>-@I>~pi%$GF zd{q)tKXg~IWx10UQ<{#Gpj>aoK?TK5}N~vNy%=mw%bkWBP(cZg0 z9a7vhr--iIV#YK}FVD%wT=C*LFEdB!h4StTH+F{mFSgFBH591%cuhUNj+3`<;f2S` zFsM`IT+ zEO>v!=y#sehHaMf;-gQ!-YC-kX*z?Mvt77W4A%sWir6#yN9Pu;m2--nzW%Z}=hJw*tyn%5J$?B8 zWWLL)3;ppAROjw2yf<-aVRpg8fXBS*g3iWCrKk5WGs^|8%YOeZZyU#To~$*0KYxq; z_i*2;gAYwtPvc9`5zAZa{rZL9_Ny2ATHU9YRH@p;8hpRArgY13rIO;R9|_C*AMOoh zJG_2sdB}=E;uncrVMe19M*?cpP4`?i_s0q z6S12l*B?4^KsYS1lGW+6pQk}=Hv9Pd``HCp%l?53hiI`s-Fvy>P+lsKnetbU++(?+k};qDb?yPS>p{1svj6yEp$ z5dG)s|JS=#&W|#$+ZgclkNE4hhM7V;+E!Z6-jM#=v2?M!?w{L9FGoM)mJ{hsjaFnXjdo{8Hv0Nt&B;RmMJ_!h0c$k8HV+NP=XJGYLZV)ACbz8OIc2j2Xi zFS>rGbmn~9Pmi^~+`c{Kz3uXnlO9wfoH0 zsE@u&uSuo_yfaz#ewX6sZt3}<_bk6{R$kxt_mAU}bbqdODc{>}{++$$l)jsLv)Ais ze;40U_%-vs<=yQmc5$~kbwxHl5oK+XR!X?b)>N+d$j#j;&|$`+P;o(}lvLv*rkp(2 zXKuRVYsT3rZ*j}Z__TGtSE&{5i@34>J@XWXggY)j|5fb! zd`99lXRJWO#Q>?*pV&Dn0+|~xXLJa$bR?xS$CN5Px-=m_fOFO5rH2}BF)uw|^Y(R? z4zu!;=Etph+zA4<>a~xv@2ksRR(cZqn3Z?mYw7gDS%%X%Pw`gv8XU{4`Ef+4hf_@a z-NMjQ9Ou2g~qSjnNxb)z}bDTWf0k)xf^X&!JtbYG$AH(VAl5WX`KbuPL zURJ2+koGY5TCFEKm*brFgS?3TrWq{f!Yl=iLs+@adu?8I)xY-Q$KCS{q?+%&`7!s% z{3og%AGBzwdazweSDkBl_D%XuBY@$BY|2 z_;r=$SvzStYpiClQ+oKpzx3|+$A^}O1{WTg=#%nSDwmL-23%% z_S)Zfu?(=XqW z^xkB6WyThRvRpm!@7Akd$Ujs1x_ORYhj8kr7u5oWr)K>P-S%)!(JAZK_ag6I*!SrV zXN-jR3Q>{PXo;SgTAIncT=VU9i?bg+I{7r1TPy!hf^3s@{VLTwgAcYXTeO9y9roGw zap9J{NcWl(lN@LEkbrD^0l-|Ka|^~2CBvo7k+TVGQvo;6?5+jRxws`Re# z>Rl{{x!kVLIrXATP0J~?uR>kO?y_Bi;QDW_bHsZ)=iJc@&p+D!X>% zM5yW>Q_kI0aW&}lldR~hKaJBb&+gCft5wZgWnR+uc=_U<_U|YBW?y|a<)dVC&%t*& zcW-{YH7#?ZPGnM!z37%({Vl(K*M|Qt5xo2Mp=;>Azj{&Ex~rIvOMYngslT^TBjEbA zppPe&c1ReAx328H!uP7^mDH*olUsnR2Q=hNSmv!UO`zdbm0Gy2r~ z(4{6Z?(7?Kwz-Qeoio#TX5{SS;yosPId?r(w#1p6J)h=mLFR<>44FZXw9U+ z@5~3jsrlbK^!AZkS-|7NMlP!kX%!rgzaX%Sh4=5%KI?yr<^;V9_4}K8`|N(lxf#5# z{+vB){@<-K@aL9KkMf1~X1w>Vx7)?7Tl-Wlln7#SMoi`Ic{f^js z=5$f!zre{W5_Oh6Ty3}b&$b%>*UtR=KdK**+gT_7>$dzYQ|bNf`%E9Zf0X=d@^j_v z<$w454OTyQO8TPXuVs_Zzn6=gV``bY{b)8YBd8-W`6a4Ua>w)GX#Z-7j`$kxscBhtX8d)Lf}+X{oYF5l@sBa(Hd- zTO)JMZC~fL|6i7$dLQuXyGOvkPuWku8NW$A@$J>yhn@TH7jxA9{kC1M)K;|e@44Ui zKNKA{-{;*MB|mq;V*j7(qnE^Nu7BxZsTa@vdD^^9!JAjCK7H}Y)uoHDr zwVKoEh6huCzvP|J*_{`+EerV~;O^Jo>~QShH&zw~R_~t+7(}K&^$@+0pRXY*oz=O= zq&wm=H)qVffC&}z4!LC><$54~xhjR*k1?BZRYTDUzn}b-hA8iJxyk@PDOsF-zZmF=)S<6q{_zI`4|_ zkp%}=u4;YH(_m%Uk$T_#M`CTliaf@p7u3C$yPSO2Kk4HQmKWt=^%wZ8HcGzcN=!(Z zc1-8uFAK@Or@e(C_gMIuKdnByYU*jjmWgY4Rwt@SyBVeXrySliw=w)8^V&1CLJ6!V@+`d)SqdnE|OLgbFP0QbuOh00`bWWgL=sBCCfAp3) zD|2Y7mm1D35?c74MedH6)SG^d?h569{qC(E{}Z0tuD@a=GixC|EP?$9MhK%&9D^ zAFAEWV$YV zah-p0Th9MEOD{}Wy`;uB`<||t>^Xstv&~ZrcL!V5PZ4NX8{fsgw)M!2RK`h66&Ara zKRNN;nintqMQKLJ$1kTEvW>2>Bz`}{^-tl5vkUV)Asgk%){;|iOV*f~R)?S8&Dgn5 zD*8;_`|Z!m`2S|e|9YZ({5iiV{}=P;*VddhJsFsI1{-omtPEbzjds zo@`yF{M8^7Vg5W*#s6y=0}H4*%NY+V@MZ6uvtALW=8w+OLnR#LnmI zif(_`y7tG~*&j+a7*C9sJ|92%%zBNd{Ave!pOkG944->KpNV~bjp)G$In@*VVt2Nc zPgrRZ%=A|_KqKTwcEP2n&{OM$xPE`UxiIM81g%sV&8PhW3Hlsa_H0aRT{?E<1wJf% z7h<}_?^pkP)m1ahjy*4Z9JA1?qW!$}@%g`B-&t?R%ztB#a@dNZS08NmB?#R+DSdop zu+`#|4@17Lyc|{YaLp{IoinqKeUA3du3KqwtUxw5OJ3@A^p-^9Iq$@~dH-@RoGv@5 z%ew4+Q(Jag7XEI8rJ-2!N{~?dRur%IWbS($a<$%(V?OPc(P^HYi>f#TPOW+5=FKj~b4X?Pl?mGG zHJcCh-pNo9>33Kt%#j?%m^R<5BkuK~-}6tte8yR3W4`Kpo76*-BnjT>SIimK?#ba^ zHYaszsOi!G!RH^eerhR*oQa;*ljdpjjQv~CllOZ!C3I|Wc+cGFKK0ar9mhRV3-mNI z6wWH8dD_~Vs%GY&h+pyKJR^VAI|XB=otKV({5Wrddzp3Vvk!Bx%)GsH-=}jG&L2MP zE{=1T4c&O|+>HH>->q4X>r{S^{ui=G_^bLZ;m*9dF=>-RV;e8L+i_;e)U9_~F8F4K zxWB3kdQ~!Y+O9cE^^Jb7t9!R|_3`zG+G`^X-J{bem0Q@~)e;KZ>3D`iV!N z=`mRfaCpC;w>ynqVTGMi;jeW*8zMiQk;)1Sz zc={t;@ShjYn*t^8O%twe6yQ0;^l%0jSEkFR3#_xA>PG+mz3o=-p1p}LJ|$1LZu)lk zMe}L-8&&Eeyrwmp1>bJ}jW#>)7ICBagDGG274t`Z@oP>w>mBV=B54B^Dn-8 zuzrIjhkiwj*&)81)Lv_XG#Js~t%8efD%O6mGeDhAG=Z6EQe~6UMJC}O=V$KqgeGMB# ze{DK$|MR!-{T11F_$C?%yYK(pfBApYmEO`r>Px?VUD_dTcY5x>KTUu9{8kkjO%}c9 zxpwl#SKIz9@x0-nF)>l-FHZ)qN?X6v@|vl9HxE}HDc^7KHhPwv^Lsw|86Mn653`>O z{&sG@hrEQ_`%B5}ZH>>*VmzAU>E>J*B3O5vA=Js%uW{!AQT0O;GLU&dp--V&xf=woFm$JCbxtE7MN-YI^FA^a~rCmfqIkTcbOFV`o}^ z^%{dG0(0IgO$>Dm6ylmF!;s3*cfg5Bb!ym_l>rG>L90Hb`D!2F^q;KNQ#gnFh^0Ie z%k+w^{GrY*OWT`Ye?DjZ-`Aq_sOXDzHvgJcKlweByrp8(?ETJ7_K@Z+k8`D8G@nT6 zR|@3L`ypJr>i>N|^}g?ymmm9mF*f7#kM#8O=g)^eThJ8o&olVE!2Ih*O-hl|~lfqydG*jK}-n3$q4e%q-lAG-Cr9!&^8V|Fb`C^$?~Ij77xr9s~__0@;4q!k?k-ra#u)^zQhbCYT9 zCce^x?(e);EmmoGcI8FlbAgXV9G?%*59VRxIvsMh^48)5vrit|d-Kh`ciYnMmrM!! z{v~93?60&vrTJ=`ub+sX^!dBbw0X;oqar?8{bvf=|3I8=VyCoJq{Y9#PMpS@^E$ue z#_T9a=?Dr^O&8f@lg7Dj5nrHr(E1?zMRlHk*}tm4Qhv2wgjKP)F@ecDxFvP=lPe`# zwoIsHt@-1$!B}XG1Gm_YJ1dSI6-nBsyvCpXU67Hv(c{w#I`pS_m|Z-=_E`8Mvm+bl zfzP@|-j|e;XWdxRo#&=@=9lTo*+&y}YRozGHg)KTEcE_3x8{zL@j>4oryp#r5svM5 zsTIs}+my0ZGxAX8MfRepo!d7Hb%&%+mJKg(o%2q`iGSu|bN9)CsnwFV?}yCOF`YFf zth9$S{D;7-!i=AAI}uxoCOc;d#pLasS{EF-@Yz>y;i<28FZxwby?L|qIz2tJ)o1^2Jsubr z^yKQVkklf{SflJeE!(!uNj{aMqkh?Is!^-UvdxleVhQ|Y!z&tl}FkJz~{Tv4EKrFoi; z;ZNsjTzW^pzYw|lS?-skBS)SRQWw(BJ&I`)M=%V^$Nz zgGoW)^sD=)EIv1UcTE-lE_{5}nY4EIdI#_OoZmZgVthVKI8fZ{ z^Df1)JKIR?%H%au3@Ut;ZZLA3U!=klSo2_AyGDk?1fy)O$unF2PjYaOoHy;kf7K@C zj?>m5_w5(kpUU1{+pAZ`~nug<;Q z-JNS3ZPl|cW8>kKTS9i&D2M-i8@rj!Ty?u$$25hV<##tlocv=nb5?5Q^=a?^W`?c1 zba(j!ogTkcp)a=XIrT31l_G-n|$kfG8x#ezdu5`P#ateD-;_76_`?ikH zeRdzST3h^k-*ItUjX%e~>)rmPRkY^j6oVq&y_qdiyJrbJ?w#_cXNIFjl5UQ^xBLfAh;*zsagBa@fBzJ3)PK@q+Z#Rqq~WeibZD@GU=3`9vb`L6-h@ ze|e|#ck7Sb{C39X>b057*5O}oDCNF7{K~<+?%2fSoyy1iEG`EIpFcI1`EK-<&--q# zv+|L9U}dzqcyisn{aaS_uVBhnTo_{r;C`mO7mPi+hS zTspfY{o$HJX31CAHQqZN%Iv>g^d6`E!`V*+{rOgG`^NVs>dr%re0BbYaK&9BhWnX6 z7@uDG_KNHk!B-NcGA~!$DV^~Bo{x;uqnXi*XRiLVb9El;#*eGCKRD#}rd@m3`cvWN zbl0$_2AtKWUh)ff?{f^CR_k%4=7V}%S;w}QR<+9tb)t{f&g1O0&HnpD)Yj8TcpcZr z)bpSA*Y50DGJWOcezPm4pHeMrY-T&CwMWn0yXb>&DX)^p{U?%voi`X-n@p3f3TAkJ z4ie2TXPvyaI4tKz<=?sGwXgU6?iZdO;2c)0@3Z#xx^_^jrPpo0 z+c`w7HSXEwlfA$H!*MmgmIn`RL|D#qQ9E~t)nU4zmkP7YY4JykCOh6ZwZzSEm&AY7 zg53gldNesJq9?sbG*pXX``lxp(-C;8X3~yHYRO3tHuK-lQ%JMDB(-hzFO<;S>C3Ym7O&7cZ~>G4o3>@25YGO8*O-)Frpf+p?Qa zbHennlZr2bPo7E<@;h}g$Zh@ii*}rgT|9CZC2N{pdp&MuYqQV4t7Mwq+U|Li_x!_6 z297QUkG6h!#H#sv^{1QD>~vfnh=sPCK3m53=(P8zn`eJN44xm`e7dZTdH(%L=kLvL z^{@TLq4)cn@sB%`<#j*GOl;n&`ddiPrigpq>xmjZzrA!4(&uOz*5w#oRPd~fe~^3k zMC+V}`2}GOLblvLxi9QorC-$h&pvPej#3sI!4HkgvJQXQ_#x=Hp!<%zUvsmM_ixpc zOLXgN%~p4tHfc_Be077&y#KR*EfspiS6Ic<7o-& zL!e3RO^$!|ul{uNEqnRriOrq=-zxvx->-jIdg0ilh6R^@a1^I#?f+$8*-$O8Q{dRY z^zy&^?|yod=;OsRbN=KD=kNZ{eYJSKm9?$W)BvWV|4vpP`~R}N|8M_&_Ag#9jjK*d z?4FX5b1iT|!iR(`>7KMV`Kf1q&bjNeDA@67+V$>#9{XyJ=~S)F`fRD|U&OJ>z+RZi zwR^U4&n8w=rfJ`K7gw!3?!QHE9>a{+5<9!pY?>d=(a@6IrJyD3o7H`J>t@;ai+$f) zr(L&d+0N}a^U&=Tb6Zl3{vSB{e*gOey)E01|DSp!xsO9xMQ*d$PwOKQK7sq0_GL<) zazDD#Y*l}h>x79vYR>V#_ur|=ceT6n{lAQ3|HTwGWj~xA^=W2Nt(oH|o1SgvDj&)W zmHFG&KL&7a}Wl_+=G>x1CqApClY9Vz^Cap^LC=zbB7?WwSZY zd~p#)PNfsdf^Q9*Zg8&)Ty$WXuv}eU{`tn2Pa0PE_V3x4U~OdcI5$r>`+s)vYnShr z_Z~cW?4GvNhmGm}%(7WK7HuyyxUpe5yZpsHFWIZAo=;-_yZNTIS>5XDZ{K>|)%ng= ze~#a_U#Dh=>7^GTyt)Zfd0(gH?OiV2=bn4_d(PaQ>lVJ&u;b$1wSQ~j@i*@lOKrB_&yBN zxq9kpx<+nxMbjtKfg0>g-TW zi1fD6{3G^YiT)3r&kJS#*{7}CxWF)8^3+f7W;w;!DSASebbL3r2K#^DEV14dyF-U} zwR4-_!eA$MOMUz0HJVmpKCkDynm>L#Bgk@@KYOe1`9p;(_j~?d7xr7P_y2+A`#AqT zI;lQiroNo#s_ls<^XvcpNr`ZrozAJbGzLqrzJCl~t=+t7e=EZN4FL z_W7c#Dpo3O*W!yg89(+}E zOx5XLlP+t?fu|}fy)9d=20vAuVX)P4hiOVe*aOxmzEkmAXFiENIjtgi<(jn}A*oC< z3;Zj1Bqc8w;#sM+8nPy!Ci#Wz6~Ngv85# zKkwhT_GhQ=^zgGcjf`SXEG+mJ`f&M*jAw_$TME+zlj8U5?VmL7#)i_`&t>nfYqtdF z`~K0kQeI$Tm1JSL<)qHf&5LvIA6ovaTmGKuxxoM4a=yZK zy}K`YD)v9|xjC=%cHF)xT4&CB+HT?w{#&DcJ});HM6B@Q;US7>vvZ2 z&iZ=h!lU5pc0X+Mccjm{RAKP@$nw2=5AkP5mv>iexRP4rm2~9Gs#&j=iv?+~T&`ho z>A}0aCYuQtHt+lM!e%~q`7T3#3v=&J6SN$r%cqt&v+(gTmgrQiZpd8drown2#xV4_ zYUPC71I5QCoL|>w@ipn(2a)8`&}&ziD`#@wm~qov?BUsK76$nqTPjQ#6Xx8V!Zab+ zX76S@al^*cX~i=gv^F1^5EkrlO0vuQO7XLE@;Visf~A6uQ9gcFx*L}4c4kp)`C?xf z)}VG(>_G6uMVhBKoLMTc-FDZ5#)j@AzOwd--yN=t*)Cq~m6__lh<#g*ZC%ak5AmO5 zHy6D8as1;GhuckQQ!U?emLBO@CYKzZ`I+e?!~M`}dlDQsAM^N~s<$(AS@O-k8Q0P| z7cYMO{@#X#+m|Q*dw1}sZ|~=q?elMJUEy4DwDaG_r~laPEdE`3Q`&76u=jQE7p6|% z+b{Y{PfWB9*q87~#O{ssBn92YQ(uL$HHQkn4$$EFa%lJU_4}*;Zub4mUVeUl{l4=K zqF4RS9u9gR^-3>kq2?*(Cuh5Ao?XgF<9PFvH91D4|KTnt5%x8653ZaT-Fm+5^UTDH zE~>|i4CD?w+R8b%+lN`Nm6uo^I{m@Y$Ffn6RGPQ5G&P;sV;m7=He01L>fqBTpWKB1 zdqw)^?2d?+;|^K=oL^7s->e=rgCHHrnQ0*#Za4qdkekRLX}a0s8jH%g9K*)IMp0+a zra+U-8HOrq=besR<7B(=IV{q@_kOEgNSRAg>>Fj-)nTP2>s+Q^aKQv+}2Hx<&HdFJ@4oY)-4~jW*?4R?N;^cyUB9BBCFsm+qrY*y2N_l zzCC?gKKIotElnp?dY1k>WAifprtuWH%O|+@lz$KE{*Zo-?bjZ;NBNTMH{1+a^*tM= zSuMBYb7@+bJV5j2B|ef2z}4EZONA+m|Gfflg7pLz!b$ZV+&T#!#d!Am}sU{qinf-w0Y_rG+(n@X+Hbx zp;$k8<%t{ljppxPBlM2r%ooYMX`3${C=tt%$dr5#H06P5aDU}H`GA=LCfQ|24=R^W zxq9qTop;U_C!s?k>oxgyclD|ihIdRa%vuqUYxFmF^NN7pm&RX{bEcWrtUK#*d|vHG|0LGgo$gy^vaGx4)SK2L zH8o42G7nPrZ5S+DYA2avvY~cZBoE&%eSas$gO}Ibc@0pb4{_ zO`yYp>At&?WF^XCvMLiKZMVH)JiWBVjIv)*lj4n$IhL9@%~( zlu>-@50+yeJs6x`zF!d|`r>8R;ns^A%uEhtsHleSP`7@(VeRka1DqM3H>7^7Fg&Aj zWsOyTr0JtsN>vtT6$+$pMn3;u)7Ih;ZemLz6rUZx($hcxhmh`oLLrsh2{F@s2g}d#YvI)*R${|g>;sk8SbcI0gt;=lU7KQ5SdI!Z^$AU!xR~wpp$1pku7;R%k)ld7 zLVT4t?dx7?{Bm<%@#D(H=Yp*f{V#l9e-!)t;@bV&O+S8c$+-Vuk!ji%eqrs8AJs)7 zNggltg^qRo@lrXG<9O%Ewv~rD&U61*w_rovrvrB-bUyv;YBDc+{xmBfuudoWtX@U9 z=~K^dX^&z}_lk1!?G1eJeX`2Er4dgef1mK-6;Kbh{y6*82@j#I6(Wz8Zen!#Q)g7j zx2aHDa_-I@^PYU%Ds2>&Fm2gm&ntZY=IxE~a|=D>7M*vZRk_f@yU4Qm09X2+#E`C% zvK^aeC<~m6|Fo{jK)KWPi#P}C--^Rm7oF^Sw6dr_Ty1WaT`1SG%iK2W?x^NX{rswa zCx7S~vybOCeXvuU{&Rb>SoxuFmEyPe`gQC#W);fUsr>n{&RVu{PK2Je{i?@)C24erHX+ z8*(Q9tJb;ip@okNXL@e%DB9Y3LTVn%zvP7rE$6>h46L?&o6h{_S*_)Y>N>?0zgIr0 zsJ;EB&hUY}_i6u1<7_T&{Ov{U1;wU!zI7` z*4j>#+nw_G-}8*gUS+p*f>)+YvOg8Vyt*}>^Sk#|U3os4Ez$8e>fN$K=hjBV%i3gq zsx;r%GtbRu5>=ak8Ly3&3wP{$*1DtMYJV8#d=n$9 z6MFuE<{BC&pH68qn%I;2HH7)9FK^K56}eZ+UMZAnPx~mhc;525CTZapdL0+D+&V2R zzgDhh+^?Rt=|s;y?$eDci^ZAlJ@TAqvGaq`p{KDGsz#kQod&)_tD}uSI0$Sw;+(rs zcN+hs8E+;ndo=Z8lGc(#hvH8>Sjqcyy~1T~h3~>Dg&R{vB3*h4vo75{_PkS}@7g6d zWjm8dk)m5^i=TFx39k(i6F%IhaYvr-H$xXqil)K#i==C#)o-Bw<3vyGY?*#2K)>k9eeNolf| zvc9I-N(Fd|Moo2U49V(^(Z9Z+YW1uzt&pOb)2?OlnlVq(E9B9smE5`G)s=1S^7qXC ziT5(zHCzp8Rrh|5T~d$G3Q`ysD+HBCqVY z^y(^>U+cZ*hJ6+PlD;)=y;x6u*vqf0`Y+6%5VS1lgvmAYkN(p)uZhu@{eN=)3)>z) z#pI`Loqzu?G?XxjHZx||@ml}k=Zv2Z-`(7N;c*U@$H?x!ypZh7Xzwha9+gUgGP` ztuyvqeWvIp`HA&$+U}!gEN0bwv-0_LO-j+Hpl(OWwFehIbj99oICr&Z=PusqhmR#0 zrzCrSc%G+s`%1UHZ`<-qxp%|g?4LE^_&YnD-ikjz{C2!%nEqDcSnfAzqrD5F&zK#Y zD|R?zN8b_kN9{df`8T#rZdfj1q`Y$Th8fd}eP($2Gm5pbFWz%Bhbh_mfx*?wi%!b& z_ls=W9d)9q_0DIti}EgRzxPZwNQe??*zFXc^E7*sfNQH{TSBQp%8|Fs^Ab3=t2BDe z;JVT_bK-{}_En`V*@xqMTC?3FxDJS_ulU<_lsSrZuE)0DYo&Tm-fCfsQ({-Cl$ub@9a%I{qwxB=#J8>%hfxVdwSSQ@lE}dx>&WK=9}u(czfliyuU7n zIP1nwJAAy@Ho$3V`g$W(O|7-s-&(v*YbSk-I&-bvJ4oC~A!ZGuAVW;W%9Ocx7c76v z;J@7OL&>2z|1%;}MLS;_N)}Db;Q!dV>A^PjyN#PNLVd*#erIM)zVEucM&^HO!Fr1y z^A3b=JuZ^I#Oet%yT~#3lrs5wS9#VsK2rJj>tyxIFYNE7CmL>Panvy`y5D@cbw00d zdghL4m(25b&P9J*h=ub$3hV82GMn-fw>EOOf{DP>!-+eWkBk@)n;> zN$M8elK#k?Yx|XyO_CQ+mUalKOS;Bd?62BzXT!reKd)Mw?teDVc>lRHGyOBG7*E9X z?f#OP?y4f?e@*DKtNwIB&!AMDz*ytS6I8e*7fXF$ey4h_UHoO?la=38J1?(dy)eC2 zt>$dUT|MR6-jkjp6SL=ijNNiPkX38e##y18DiXai!j7$Z?YQsT#_6|P_;-hUU*S=c z5n7p*+yBAu_hOvnGv!Q@_}V1#bE%@$tYpE2)p^x9yFYuFl|@yg*JTyF!6o z>pWv_`-Kzri_Uik9{;d#-lc7kch64!d+2Pp*x$nRL$SA?^aZ8=>-<;ik}mo3{q4-> z*M0xUL{7Z*;AQ-SYZrg3rGNNY`)cv26%wVkQ;X-_?L6JF@sQJz{Z94A&cF2csD06s z>h)=-(4)o>rk(j-N9y#{)9yO`S1b5Gjm5%&`_wdNH8uWucPA|BJT=X-@qtKnaMCq3 z{&z79YrA8oEC^B8zR^iyl@r9g<_QDew4qX4dlKk0TmR zmwh{uq!4`jacc%M!}I=yXXX^|x~Y8VjmeV2%UO3`uQK{`;^MJs-~2kl`Co5-t0gqW zPryd#H&d#2XN8G^XPjPGF#lb<-qWF~uN4j*xN?}W z+d1|1wFp%_)i8LM@U zD|cT%`QVCGWYIZ>CO*?S?Grb3e%zhw(D=$z=KUUSa~6k}`P{{A7b`YNKKQx0x#D1t z-)!S@yEi}7It)L~_- zop)?Lu8Z{3mNT3ZB5m>b!w&=h->Z99-VXK;d0l$#_l1eSeS-Q{o5d>bDPb-Ce&xqJ z|No~>&fAn%RN}pO<}Qnt3*kri)j2mdiaIY$m}nZeW2s4#dVwp;wxYZ(t9GsP^jY}P zKUYqCkt_SE&Zz}O8BS+htM{lkx(V6Zax%)lG+Yvpp<48!e(j@n@wYc8Zr=WFk5$VQ zE~)ZQ5+z2PA7@`<|FP=aQn9A#uSEDw46bH(>)mK8JbNG{p0|5W>E`$L{9SvBL?2Fl ztujA7DEUf8s7|Q*uSoxSopskX=2Sx zMK=$1msJaV(RxtBwZWBPh73<6m#Wd3#cqKtKRG8@D|}@N6!zBN#qce2>;9>?LkdNe z?JI-MJrJJ#=SAt3$jfUkUTpObsrP%D&uzX$-z?&>s7=4thvMcPKbOyc6y5wokeSCO zqEp`H-=d15yOvuI&9>3s!};C7d-*Zpz=g)`H{&0DT(j_6K*ODP>eEWzihNLr=y0(R z7mPlnm&VO;tRsJed#n1kDF@s$6sMPJHJb}=j`un6LjT}mRer&YgUcs$E%tG|c;UI> zZG-Nv)QDZX1h)2MaWja8#;W*A&(r+!9p~PaZ;9EJ^!n1zHDAIHB|cnlAMxvj`&^BhtT*=e zWp=;!QVDGD3jcmqK5E~GoADX-2|wFDocz13%WGZLY2WvXlD7g*ELZ-O^m)q6O@Vr+ zyjfQUt!jF;Snab$hw&{fBPTniKTm{(#aAD>!x^UR(iQzCZ$`V_JI$4T=f#|lWG}m8 z@ap6ADV^UMl}s{48d&}AtWKErv4dN|?115si&_VYavU0UWbWDcK2=kD_qFf&$CDNJ zs=s&Zn_c8?l}R|UXr{ih?SZFX9!>IZm6_FPBFw+AzFshQ$zD~lTdObn>`B&~S+V?x z(Z@bF=W5;M-`ko>VU>QedAjSh z{*%dliJX%!o_YGj&$nwuXp!4Fw`V>oE{l{lH|yPL?^!A%@Wi+%Z%Syq zDIV}+JCis=?QllTJR_?nk36Xh(?tTj6nZ9T{O|nDV!M>(t6PN4O*5S!`yIKS?|DR| zY9%837x%XR`_tiae9k)ulixSyUp&8W@AC^;wVQXXHNSZ~I`-c6OP8*0-U+n!oF7Nfjmq$NdnVEF6S3Dt?@m*#|SCHo` z!$*ZrROMXD9+iZ+@h~$?3#jHhckSoSMTYUSt}vg`m0%015b*d_(9CMEW~UCnUbNrg z%M1rX-*AUJ)T{5zNi}WRE4?X{Q)21@@ehf$6H29v+cqq^+qQgSjAJBEDCdsFJ<6Sq zMuCQzC&CkpBPShnF;clWyF2^K!K7m`b9f$Vo{vx{Oxhq3X^^jIEWMv8!`u4Hq{APD zxc0Trx>xOA@p9|&i}Q}hzp7vJU$v+r#=^t?!zF>d&r=g3lMgv={Fr^n`~5*-zyDmf ztW>TabZ$Q;z9*z2hA}Q zXee7a&5>#G5HC?!eQ*n9w?xGS=)2k@C`p}jrr$x;kQcNr-xftYZI2E!?Rl0aXcmq8Bwy11xoUutksdG`n zotUSSqItH=xYIoS|8H%bN$r=n%57V1ylvTb&-MJ4C1t%~kwJm0uCC!cYw}4W#pquB z8Q~L-{zGIPitxFt<}1iwZ$lPM^ad5b>z}!_cPXq+KiXC z2-okLweR!v4D)5FpMI>8b$?f}Ls{(7Zp+#~2d0VYr3X$ut~NFA>9X5zrb>6;^|u$j z`Q|H&l||m_ZI@rJ+50?X*P+}m1;1X|T7S!lvRyv$u}RP6+fuXd?#((IDtoA9!=vWg z{~Ld~{w&~<)^B=x*e^?X>-1fHySjgAhcX=Zb~UbkykOrwnbS)a&#YD8O<7mG>xQp zZZV38lAM3-rfKrq)PPMFCX{s>RQo0S=C0bgb?x%1goBHgPG5I_OXcgQ)!$=(@-pox zR^C^5@4<&jZ+G*>6#w-NC~AMWa&_7Ln%i^B1>?+OPfK1(i}*8VtA~7NSe3L@`uZDN zf3ITRe)p&U!A}=|EpgRi<`L;W!}IZG+K+aB!|DS95f(9=g6T7y5BztU;c$Y>w`a2H zj3Sk0#YlrGD$`2uaLkHYA|xr{sI$pQmZ@7mZ^n^NTzQ{FkEGt*`hGE+NsH9I{oihV zZ+*|r&wanX{^F)7-S5Bud_Lo?X7Jq2d!ByVzH{0w^OkD;*zRfnmMooC{rlUr1@AX3 z{~Gc)A@yhK)2Yp0mq*#kXKk%7*gn^bH&jhbRjWN{`K>$k7qTX9+s1lpy7lX8T;KP7 z6y8#jdrG`T{n{n9{p;tKFP*0Aee-O5_m}Ur6&p9Nx478*&hFvLwWVurY^mG2Sn(le zm0|mzx1TDru4w%={Crf{e%iK6t16fFUz>JqpZT574!a-bdp*6+^OpY$&w0JM;a1gw z@0oMk`lp`i=gsB+qSv(OWB7!sxS!jDH)`qci(GZIzw%J?`?@V9^Ro67fBogFEwgp& zJmEvDgy*>&ZvD4m>x@+;fyFCSuP|Qmvibh(nXz+ z_LrGgf8KdzreL#rd(xrJ23As9yB}%oXFYVqLHm4H;q^tf))F8#b#ryUJwBi4yv%y)T=^qU z_tyTX(wshX>Zvt`DbqwZG?hIzHM-6cc~Ws=LAtG&SI*JUlV_7&&0gMg@5H6l-4Aba zhj*{>v!C{6^Y3+kvW}E`)UvE{VTxmoIx6598uwt5u3Chv+DcW&n)1ChO&iSY^k)^R zK6xB*%u}WIgHKXL-|QN-rXy}a^URw*`|Y{Kt~=*Mx!tjh9ebC*xx3W(ZD{CT=Ti+; zX7;tm%6&`dS=z%gYV+DsG03uwP~|geaA9>!{oXnFH}vk3$C+WeyVq- zPP3-Vd#1Ds@AF?WY1+4Hem%c+De79T?)2AYXEs@hOxo-Bd|Ks3Q>(V@_1laZRbL(p zn!PH|Y46x?q`I#@2U6U-!G`zc!D$8~9-E zt&j7*%Pc#Z8Y1KUL$;#sorB+p$;=%qw_ZGRswOSFWXk;A71lm`Du2$owt=H0IeyvxQh$q(i-!4e?yUvKx7?ME`uDc;F#p}`TbmaztmC(>4Xc%{JG<+qS?3ek z&XkWqFW)cee;stI@n`Q;+10b#lKd=nH+%VRYL`+`WqvIy^m=ja_4!?H@xj`sz1GQW zJ<+UK-g)%Nsu`1o?rC_fm5!)<$@S}4Hoxh&#q+Q8>+Pud_vdndn9c(I$Tweg=Ils! zWc~Ys+tzg7BwKxtmfL(4`{cRIb!6ALd#ik5t#FLf;XineZ-YZcz4&GIUyB$7y;8rj zHU0baRCTRG%p7MsUFFZNDhoefyRCMmjCWT3@=S$$dC5K(r|b_dez$0%&wL5ds*9Yv z)JyJfdi`2^dhWX&=iKgTmbOjWR|Cxi&{u9iB#e^<>i zzbQ`*zZ)=LSnrVUYQwmC=fwo>laHsaG`3lrc2;k@o!+XAQfC^Li*a-Zf6Cl>DDC^v zm1==2^jQ*LHg0SVarSjdjqpfxZ(iOdcIGCV;m7i?OU_$G>^hh%-g9r|!^Qvi{f%2< zSrzi*%e|7>Cl76^3$`is%v-WNUFEybKMxJlgF>lRNnC#U{N`mZ%;j(INey$}v+~z| ztqFIJBo&>UbL-=Kckzep56=F1@4hvMp?etEXh5z`mk#0WS)r=*5(EM zXlZ$BC#fR4y+e|%^Prv5B9{l9{uhiUKUm`|RMU7`>gPqr!#nP*ah&t*%DvbAv9+b4 z_0DHro2?4GbikwPdHWwO;q;)Fg45hy@9rs{R1|e++5e!uTlLpY&c6IE8C|!=_ETR>>Pr`YNBid%364W91R8y+;zBMMgCRxX!qEGmGirgvn;gvzAF- z{p{Pbaf$CD2h+(PJ$#G0YCAUtJDw5T61aIq>jLBTolUW|emrwH#g90KeRVh1RY_ht z|G>7NybPYIuQ(N#uH{g_Hc#GnYrEllhi^q3A2P&WzI;=Ywrz!NzYuHEwbvRfM^l3C ztZ>P{bZFZxIW@CAZ{Fk`Sf;glqIk&*PMb#SEQ`aQxf69odR4jHt{aHO@k(k<{aC!X zXzA{S3sMXk@($)4oZ`h)JpIDD2|6#;cd=f)I{%U|D~sYJu}MDGC>1g?jMI?mm9NUrbr;cr|e!L7DaJX+p}p1H92MB$$Y?dIO^#O&;?HqTC+BGk9< zQ@Fj;e~zQ8egQhBy7z;p=#zw( zk~VAfx*j!o26E~;2Q6yhGe~;3H_NY)$?=x9?8QR2z3x?QNpGY4mI}VIH{4;$b?=al z?cZe^bQ_KxwlQ875P3L0z;EvyTh%|8lqOd8WJElYj{nzCW+Z<~Qm6d(ibsdc=Y6it z`1G6Upvr0oo%27IDBGRCnLp=8M8)X`SF|cN3-ImfOEdOn(f{>%{l$tCCwgY;OpgD< z{cuWW&ByQYSJe0~hWGt{*Pe6p=g%3!GwR+c-N-unGiGC>O6b;PxlPPziF#KVi_NaG zu=!t{FBg1u*Y*$V=B-wi$&EE#mnEFLBx>TCZC4+9W@zXIb{ve7t=N~<*sb%>jd|88 zi8GF^irN#qJTf~|c&9BqxkTxZ@PcVVON;NsIPhsHJa2j}&^cFp;*#@+G#wHxp6tq! zeUxwACA0qhy}!FY{JW^$a{b!r34bO8EuUWcH|O}Q=j&g;-u>>U>1jV7`zOzK1S#fn zUz+0hJ5RAj^3kE0CQ{l@Ex!MoD*aIK(0-@1v(bE7-A}G-W;~r_`s1JZhh(d$^~J4+ z93S4?Y$^Fb@cGlst-)_Y`m~=Y=?mpD_Z1s`o8iLa*1%<+Sy0~i-r(grCBAsazIpnN zI+v;zSzmO2k@U88=F~L5EWZ!S4gOtx9Pf3yn8_=AZm#Mp&siUS?`ygLJ?qu-khD^h z>$i5=$@M4e>0ZCEn{~$FgBlC|%Jw|lGEd@)!OuBLA&jOya;fV&)5`X-8ga;<=6&CC z(_jtT^A8V2XKcRhd1T^T5s^1{RJc_CDjkW-wF|%Pf2qLa@uyP}>*l9CdNIFo{hy6* zw(baSD{qp25M`77YiFSAiel4`S;i^e%Ne(C&oMQq3$Q+sTDD{p``RB?8?{+a?6h3D zf69jPMg5v;PDv+>btliND3JYnpzMgc)5IpFe}}{vUg*r_S$V8lK_NJ_dHG8In$^B% zu5aOZC@I-!Gwoi&yINsIw4j9tGC3M-`jq8$&`zJ z;!~!H?2Hv!dT9%DY<7^Bir3_V$L43fG>djE+;-(v(MGSOsp(xS6O_KqFi)APrOIcM zz9!vGg=wDg(+RD&L|HX_r;D_mXN?oQCc$K}DnXGwk8$liLd;9vVw0E@?&%aG-*uUcROt(u)pXq^h7J4McI-c``>73#%I1sFsQQU&HYCfY%A<0ZI`&LD?2Ui^Wq*ZhsS?e zI+zMnSFE|uDYzzL#+itnfv0km)3oL)W*Z1{8FfYQvb$>eG+kMgB!8ok!QjZzG}||4 z*WA=dZp?eJ^r(U}TfxKf_4l@OtX-(MS#J)Pdxq57$Sv<*y{`-Z@n-jy0+#uUF7GJ1 z$GJI5=SX_k=g!K4Uw2nu{qe>oa`mhz>zTE#CN&RUPMhKKdd-3T%i9blF8Uuxvgb~9eNskI@6qsSvl z;prwm7MZ}tY=OIu95*Bi|4#_yymTq1Kysr%Cf~GP^9;La)_Zl^|RJLyKUe5XYbtSm$}XC^yi4xY0s(KcPe5@;8dwSzn_aq_D*%3ZX2U# zxia9^6lbrcL2Co`Y;p=DKJ3r*YK`3((74lEbe-fOUXiZW3k}8@oaUQCx>rr$-grJg zX2P?d-}bxPb%yQyADz zFjU-{8{+FPW61NhM&;(x*o|4OEvHgjwE|VXG3ByO&*IxVOpzm3Ui^)f|5;tuqKAstQ%>CW>b?5(uX4esv$Jnm+!oJ_y**>T z>k`?Mw?((cckOB1Cp3H88`Xqrk@6*b7wk#@tL1Uu;FU+L?w*zFbd!$$x|{JXscYez znF*iD+k#Jbo-UsHTDZ8!BAZtypjn^i$TqgN`n`*%RvPY{6fe5xc+BfbzbAaRnz^6# z-}Oh)%EzKC1%J-1WLo#&y~Kv~dyX*uZat@djrYmzl~vsO`la7O!+U>!S^TOn|L_fy z_+@49XU9+A-Rk$e)Ufj*6?gTWw!Z|ZQ7ZJ%1!%^N!lO&yW?M6&aeOWB@yQ) zA6c1SJpcNgA7?hbopgTM=kTgyf9~IRJJxtCC++Rl%I9|8Ht7-jHNLpY(s(g(Vx@FS-@BJrY(`URrsIQOihc zc8GI``U<-s;h@Wbrvqm%EAxqUvUS<(U)%nRnODBob(Yqw+Nh|g?k#J#@V|_Bapuy_ z<*S#>Ubx%O-%H;)fA+qHeKY^*{Hy62qEO^(TlF}^e7 zj^&-zclawbDr7!9`N;F(&jZoNrKhY-0*e2!?C z;5W5B8a19RVMpeiShr%&3fYT7hG~ZUN!gE%JnDIL>(Nx9MMAxkgeIMyq`&lx_gC+~ zlghOJdb))jYw5|AEH|2I#B4O%C_H7}=}V`hChJb$tF5m3Joa6y&AL6dKTBDeShsUI zbG;W86xug~68>Eh|3jcJ_YMq^O$*3c{lUcYFL^)K@#ihU5Wf0(ZF&6t#s8N46Bc$+doz26S>e4UlTPML-tPNw)~1B46IXIC`z$NybKHx!J`+1*YjQs8UdvCP&!?Z=k9@Et z;p(9Yt@>hXBXl-ZoD}L^YCmmm#JAMS^IhAfny&T<+Z$P%bhc}&T=x7m`!^I`JeEG& z$t?HwnXNz1OxvP+dt1%zUAfVRw}s!nyzTtWx=i-te7j|<%W7`#%=f>3Z%QrOZ?QM& zH}4lTymYwGD9nDA@0-jg>otWguRYEN?p>UEJfhFn>f7szQ=FZ`#eQLPg{-zd-g5LM zbNaVAqL$XL=iJ)4=X06(x!6BNnFmwXo)!&PSr@Z&S;5@Lzb4PN-0pXmb9eEhyo+~L z%kSUK-kD$g|9-PL|9RW2sy8299-myayz;!syyG_ezXrXSdU>_{dhxv*tFyoOy}Y~d z`)WIh+8duYzL|V*dF1@R`(%EqeY*Ry`aJ(;`SiNHpFf{XKes-6|JQ#Ne{Oy#KXqUJ z|Ehn#C$cl1et#wboL5s468;=eIjL}nfysxb$3f>9!=gtHObm+7jPn>OZuJIvdoeo- z)Y^8=S4dHHjQQ&16615sLQm!ni)*1`M^mKwOi!g(E=GomdN!@(Pt`0ZlRp=K_S+L2H!9PYbOyk3pq;|veV(AZ(G780JS8T6fl>V`) zLXdT9-bbOfQ=2O!vtJ#4BolUZ`BCi~VfV$J7e2^|{L|GW9QB9oeB}|vTRV<3$i^)0 z6x(${mFq%&)u&7p z_PToHQlX&eyRDt?E_sGO;mw#cF;!vvzBkot9$seqBmDdE^&iYP+S`s++{z7SopRel zsC4Q~wV67Xb&Y%9ZnWJz$JgxinH5u?Y+D*JP2`}%w3!ef*(X`n|MT0bs81=+?w$VEdm{5OT*H3235BvHLy5^idDvZME>gPP>%(Kug%zI?x;ly=mLZi+T z1%6fyC(cs_44Z}0)z10PVcwi5@a#a)1`{3T(}#*S*sNjDKIFB*Xbsc-=Fmjb2-#~5 zrir={($^YG6Kx~p%^G+Um2XIxHTouUXa%%N@i@y$U1$-MXg!-ye1mCQ%i4tO8*I-G zZ8PA1cDQTg8&O2 z5eu1+3l8mK92w5+JO+u1B?p`2Zaiq2#Tft3YPbNJE^%q$R_!~6We&H}kP{Ne{%3j||$rXN^ZAQ{6K zeqd^WXbkW516vDZWBAPv^cD!;;n{v*ZGrS1zVZWe3&ij6em}6cK>iLt|AFQY0yaGT z2Nr*ju;KGRF!_Us4e$8_n?K0d@arGw{vfo6XZ?ZIAEfs1+L2M82`vbc_$nD{m zKhXX`u!d*;f#n}0Yxv?1O#dKS!+XD7{s8|&_YcWGIRA*$vDvrBAJBgo{vrDZ?;o)` z_WK96f2jV!{73K~OMTn^1Mv^@Ka~Gq|0Dd5^?%#{1LZRu9FC|gGw78(lf?Hq;(*e$ z4L!^j-06=M&K+D@kQu`^{peGn><6EAFs)&(W?ceG0fMGY%R!*VZVO# zYeDTD2J<7m1<7|<%#SLrNf6Dp=qb%f5OyyRF+Y5^ko%6%_Csq6rRQ|teq=MJ|Mo+s zJ96a*WDC{rNR}UrEi}I)`~84zq5d7|?+0rO?eEC*A7K8dU?ahQ(D|c5$cKWEK<_>M zR@(v+q^&a+baHR(7W;O=jXgG|MedhGLPxSipRh$|_eTyJq5eaQKT6n$^&fuxk;O*P z|Ip-*A~vG_hcAERu@OFhX!A!I8}ajpKYwJ}BcOk%`=ihv5&grbKXUC6T7PKuN2xtx z>kq&F$hJo?|IqA@VtYjM58wXCw@3K>q1_+l_K3ef{QDzgjez{2_K$)!BJziif8?wY znty2dN68wo`G=o>WUUd5KQ#TLXpLz6;p-oHYlQC~+Wt|t#=KB*U;F#V>^~IiTI3(A z|In;!oBvq+hiYAGe7f^(8L3&;M`}wmR@@JNv`^~$)*bSFzpL(;KiVhxUAfR+>U;6x zeY+H1y$+0zH_*SkG337gcc=STjQ0iD-aWxt?Gw?beTl8Nd5ZjsxJGH$FLx4*M1LLf z-s-!0IycYJpuK$u4xHGO^NZ2yZjXA^xfv()%I3^Vx@CFOI&nhDt+ze-WjR;9UiqoZ zR;`PWx71H-*UOjF z7TCrvWQ+9QV*60qvdmR4!?Mc!>b5I>jeM7jc#n(KC7#)MXkNgH`AIsT*nURv-94k^ zUmm5jdgUg6wk&nm|9_`Ev$!i`ZhQ6hve@%mntRrLYgxYRR-f#J^3_ufnXejsO;S)} zIx3KMoP#S!&OEv?a6!Io^hOtJ4cA3_ZyYL)W<1zfWjRT_tuA4kdT`COMVZ?@^fz^< zuC%@oR(dcn_}H0g1)J8bWM8Omv~EM`WvwqE;fe9B(*vXTD7en}Bcf~U@w@F+=axK< zE`j)noBS=SGgjS`4c{BKb8QgE@5M3k9)%Y!uk%t+NU+G;_O`+%e$uPIjWL>XOO84% zWLLeFex`WQ24^rRD7og-`yX(U0QeqA9vjOc=o7MX8W|z zuGIa@qpsx`E{x9dpIfAT)$lfp^}=nM?lu#JC$pIB>b2qC_4LOgm%xp_yOpnA7V(dM zQgT(O%=@d+ysYhW;=;&kM6jDzBU~-6d&7*lvxRs*k4VtoIfP+~%{} z`$3P>%u?t33zDa5R=2osS@@U1h7u1ylEyzD!seyOp~+@hh$!7E~8y_EB`)+?E7 zW~^octj+5T-L{KJ=0<9^=9wI3lW2Esir}AZj`pz=%GL($p1)h_B z>F{-TU7N&IzRA~Zg13}j6=!wJo1*@*?|DmJSMp4?o|d&eY9UD-OXS!}rs}!6ma5kI zm_J>eyy(EkKoh2{=>pFyTGV-TOLUTW&cEq8uz=Ot%}yomQ%0ntUB)yI;R@fm8Fp88 zSMGBA)PAWv!D~|D{JVv7_~xc{F?U^7yHwJiw8_CxywN68Pe{{K*-@=fJ@1p4pcwW`bd3nF@{+WjQ?&MmP0V3F{896V z()0GT1Lo6`13vai&gGga5Rxd9l)7%pra2!3w_Morf@Q9ZohZ9fv782Eza+xF66V&1G( z`%NP|RyHshS6i`qNzHO=w$bb0oW9v$SL`ka^Gn{pZHrXyF1xa6vTb6D^^wwbw@wM3 z^^AG)L-*h;=Aa2zoHFvBY8(sM8=`$wzim%R$CWja!8PK-0uwz$bW;8;D@odDGrM5t z8>5>7TESjhEu-dyMRwJBNP51^-o^4dpj#zKdgatR1s{|8=4zHWvQ80yV!)>(DEjk* zkx$}QwqLDkpVB6HPjSjn;%Qx$AK+rEWPPwT-6>zt@#xiK@9m?Wote?ene|IV_{x`! zDjLc!BEL>~_j@Z(;$)4@0voeDuY%IXqt*sZNPn8r9*oZw<$kZ&R+t+*E4N zapZEGzIC>zVAaXKXKK#-r<&yI@4PVAr)uG}H&u^4buav!sq-n=(mMLngkuK^ctaQW zgk)X4Xc@ej@#0D`wnOpX>X-kBc=~V4lLrSSl~4M5tu;I2yVu0?s>zi{%}1KAu*4SE zE&Bgu#-)b|Y0)fVRUyJlFMF@|kNa|LQQ`66>X~MHGk3=Yp7yJ30-6V4>!*i;ZzjXV%FY9|&-@JS*u&e*F@pZ}Xo2M+Bm%Q!L6p4o{J2SIl zqW`>G;_Z5t)3!d)!`$sWV^i1UOkv$e!|%!6yHv~EG_P&()op7(EI8;pdA4BQjTJ^mcvm}6a;f(r$=y=XS8gm4+ih+iS5T+=ZYkUB zYmaoFUw^z$@cW)02I~#a?B@Ht?(m-18~z+vc6j5;)u-n_~dZE|DLK{4KK85>-ir%JE6lkk*H+dOjT$y2^zd7FwRPo2G|X0q Date: Wed, 27 Aug 2014 17:15:11 +0100 Subject: [PATCH 21/82] Started hacking away at the readme. --- docs/LOOT Readme.html | 97 ++++++++++++++++++------------------------- 1 file changed, 40 insertions(+), 57 deletions(-) diff --git a/docs/LOOT Readme.html b/docs/LOOT Readme.html index 483406c0..fa0d048e 100644 --- a/docs/LOOT Readme.html +++ b/docs/LOOT Readme.html @@ -134,62 +134,58 @@ h3{

    Using LOOT

    +

    Initialisation

    When LOOT is run, it will attempt to detect which of the supported games are installed. If a default game has been set, LOOT will run for it, otherwise it will run for the same game as it last ran for. If the relevant game cannot be detected, if there is no record of the last game LOOT ran for, it will run for the first detected game.

    LOOT can also be launched with the LOOT.exe [--game=<game folder name>] command line parameter to set the game to run for. If the supplied game folder name is valid, the default and last game values are ignored. The default folder names are Oblivion, Skyrim, Fallout3 and FalloutNV. -

    Once a game has been set, the main window will be displayed. -

    - LOOT's main window -
    LOOT's main window. The title bar displays which game LOOT is running for.
    -
    -

    Clicking the Edit Metadata button will open LOOT's metadata editor, where you can make changes to the metadata LOOT uses to sort plugins, the messages that get displayed for plugins, and any Bash Tag suggestions LOOT makes. -

    Clicking the Sort Plugins button will begin the plugin sorting process. This will sort your plugins, allow you to make any changes to the load order it produces, then display a report that details the results of LOOT's activity. -

    Clicking the View Last Report button will display the report generated the last time LOOT sorted your plugins for the current game. -

    The File menu provides menu items for sorting plugins, viewing the debug log and the last report LOOT generated, and quitting LOOT. The menu's Redate Plugins option is provided so that Skyrim modders may set the load order for the Creation Kit. It is only enabled for Skyrim, and changes the timestamps of the plugins in its Data folder to match their current load order. A side effect of changing the timestamps is that any Steam Workshop mods installed will be re-downloaded. -

    The Edit menu provides menu items for accessing LOOT's metadata editor and the settings window. -

    The Game menu allows you to change which game LOOT is running for. Games that LOOT cannot find are greyed out, and the the one LOOT is running for is marked with a bullet point. To change the active game, simply select another game in the list. -

    The Help menu provides a link to this readme and an about page that contains the version of LOOT being run, some legal information and a link to the project homepage. +

    If LOOT cannot detect any supported game installs, it will immediately open the Settings dialog. There you can edit LOOT's settings to provide a path to a supported game, after which you can select it from the Game menu. +

    Once a game has been set, LOOT will scan its plugins and load the game's masterlist, if one is present. The plugins and any metadata they have are then listed in their current load order. + +

    Plugin Cards

    +

    Each plugin is displayed on its own card. +

    If LOOT suggests any Bash Tags to be added, they will be displayed in green text, while any Bash Tags to be removed will be displayed in red text. + +

    LOOT will also display the plugin's CRC value and extract its version if found in the plugin's description field. + +

    LOOT will display the version numbers of any plugins that provide them in their description fields. If a plugin supplies no version number, it cannot be displayed. +

    LOOT's plugin messages are a valuable resource, acting as a means of providing users with information that they might otherwise not obtain. It is important for a stable, healthy game that you act on any messages that require action. +

    If you think a message suggests an unnecessary action, report it to an official LOOT thread. If you encounter a message that is non-conditional, ie. it suggests an action but is still displayed on subsequent runs of LOOT after the action has been carried out, also report it to an official LOOT thread, so that it can be made conditional. + +

    Menus

    +

    File Menu

    +

    The menu's Redate Plugins option is provided so that Skyrim modders may set the load order for the Creation Kit. It is only enabled for Skyrim, and changes the timestamps of the plugins in its Data folder to match their current load order. A side effect of changing the timestamps is that any Steam Workshop mods installed will be re-downloaded. +

    Game Menu

    +

    The Game menu allows you to change which game LOOT is running for. Games that LOOT cannot find are greyed out, and the the one LOOT is running for is marked with a double chevron. To change the active game, simply select another game in the list. +

    Plugin Menus

    +

    Each plugin's card has a menu button in its top-right corner. Clicking on it will reveal the plugin's menu. +

    The Show Only Conflicts option filters the plugin cards displayed so that only plugins which conflict with the menu plugin will be visible. While the filter is active, the plugin for which conflicts are displayed is highlighted, and enabling the filter for another plugin will deactivate the current filter before applying it again for the new plugin. +

    The Edit Metadata option flips the plugin card over to reveal its metadata editor, where you can make changes to the metadata that LOOT uses to sort the plugin, and display its messages and Bash Tags. +

    The Copy Metadata As Text option copies the plugin's metadata to the clipboard. This makes it easier to share your metadata changes with the LOOT team, as they can then paste this text directly into the masterlist, and also avoids any typos being introduced. If posting the text in an online forum that supports BBCode (as most forums do), be sure to wrap it in [code] tags, eg. [code]copied text[/code], so that the spaces are not removed by the forum software. + +

    Masterlist Update

    +

    LOOT's masterlists are metadata databases that LOOT uses to provide messages and help sort plugins. By default, LOOT uses a separate masterlist for each game, with each masterlist being hosted online and maintained by the LOOT team. +

    Clicking the Update Masterlist button updates LOOT's masterlist for the current game to the latest available revision. If the latest revision cannot be parsed (eg. due to typos), then LOOT will roll back until it finds a revision that works.

    Sorting Plugins

    -
    - LOOT confirmation dialog -
    Viewing & editing LOOT's calculated load order.
    -
    -

    Clicking the Sort Plugins button in the main window will begin the sorting process. -

    First, LOOT downloads and applies any masterlist updates available, if the relevant setting is enabled. If the latest update cannot be parsed (eg. due to typos), then LOOT will roll back until it finds a version that works. -

    LOOT then sorts your plugins according to a combination of data from the plugins themselves, and any masterlist and userlist entries they may have. If a cyclic interaction is detected (eg. A depends on B depends on A), then sorting will fail. -

    If sorting is successful, the calculated load order is then displayed in the dialog shown above. In this window, you can view the load order calculated by LOOT, and make any edits to the metadata used that you feel are necessary. The window is a simplified version of the metadata editor window, in which all metadata that does not affect sorting is hidden. Please see the section below for more information on how to edit metadata using it. -

    If the Apply button is clicked, LOOT does one of two things: if no edits were made, then it immediately applies the load order; but if edits were made, then it repeats the sorting process with the new edits applied. If the Cancel button is clicked, then the load order and any edits made are discarded. -

    LOOT then generates a report and displays it either in a new window or in your default browser, according to the value of the relevant setting. Any errors encountered during the sorting process will be displayed in this report. See the next section for more information on the report. +

    Clicking the Sort button will begin the sorting process. By default, sorting first updates the masterlist. LOOT then sorts your plugins according to a combination of data from the plugins themselves, and any metadata they may have. If a cyclic interaction is detected (eg. A depends on B depends on A), then sorting will fail. +

    Once sorting has calculated a new load order, the plugin cards are sorted into that order, and the Update Masterlist and Sort buttons are replaced with Apply and Cancel buttons. +

    If the Apply button is clicked, LOOT applies the load order. If the Cancel button is clicked, then the load order and any edits made are discarded.

    LOOT is able to sort plugins ghosted by Wrye Bash, and can extract Bash Tags and version numbers from plugin descriptions. Provided that they have the Filter Bash Tag present in their description, LOOT can recognise filter patches and so avoid displaying unnecessary error messages for any of their masters that may be missing. -

    While reading very large plugins, such as the game's main master file, LOOT may appear to stop responding: this is not an issue. The time it takes for LOOT to sort your load order depends primarily on the size of the masterlist being used, the total size of the files in your load order, and the number of plugins in your load order. The first run is likely to be longer than subsequent runs as LOOT needs to download the full masterlist, rather than just the changes made by updates. In testing, it was found that sorting ~90 plugins with a total size of ~350 MB and a 5 MB masterlist takes around 15 seconds, though performance will vary with computer hardware. - -

    The Results Report

    -
    - LOOT report summary tab - LOOT report details tab -
    LOOT's report viewer.
    -
    - -

    LOOT's results report is comprised of two sections: -

      -
    • The Summary tab gives information on the versions of LOOT and the masterlist used, whether masterlist updating is enabled, and breaks down some message and plugin numbers. It also notifies you if there have been no changes in the Details tab since you last ran LOOT for the same game. Finally, the Summary tab is also where any global messages supplied in the masterlist and any errors encountered during sorting are displayed. -
    • The Details tab lists the plugins LOOT sorted in their new load order, along with any messages LOOT has provided for them. LOOT will also display the plugin's CRC value and extract its version if found in the plugin's description field. If LOOT suggests any Bash Tags to be added, they will be displayed in green text, while any Bash Tags to be removed will be displayed in red text. -
    -

    In addition, there are a few filters that can be used to selectively hide items in the Details tab. These filters are: +

    Filters

    +

    Clicking the Filters button at the bottom of the sidebar will replace the sidebar's plugin list with a list of filters that can be applied to hide various combinations of plugins and metadata. Click the button again to hide the filter list and show the plugin list again. The available filters are:

    • Hide Version Numbers: Hides the version numbers printed in blue next to those plugins that provide them.
    • Hide CRCs: Hides the CRCs printed in orange next to those plugins that provide them. -
    • Hide Notes: Hides all plugin messages that have the Note: prefix. -
    • Hide Bash Tag Suggestions: Hides all Bash Tag suggestions. +
    • Hide Bash Tags: Hides all Bash Tag suggestions. +
    • Hide notes: Hides all plugin messages that have the Note: prefix.
    • Hide 'Do Not Clean' Messages: Hides any messages that contain the string Do not clean..
    • Hide Inactive Plugin Messages: Hides all messages attached to plugins that are inactive.
    • Hide All Plugin Messages: Hides all plugin messages.
    • Hide Messageless Plugins: Hides any plugins that have no visible messages.
    -

    LOOT will display the version numbers of any plugins that provide them in their description fields. If a plugin supplies no version number, it cannot be displayed. The version numbers may not reflect the actual version of the mod installed - this could either be due to the mod author forgetting to update the description, or due to a mistake in LOOT's detection. As version numbers are supplied by mod authors in a wide range of formats and LOOT has to detect as many as possible, it occasionally identifies parts of some descriptions as version numbers incorrectly. When in doubt, check the version number given in a mod's readme. -

    LOOT's plugin messages are a valuable resource, acting as a means of providing users with information that they might otherwise not obtain. It is important for a stable, healthy game that you act on any messages that require action. -

    If you think a message suggests an unnecessary action, report it to an official LOOT thread. If you encounter a message that is non-conditional, ie. it suggests an action but is still displayed on subsequent runs of LOOT after the action has been carried out, also report it to an official LOOT thread, so that it can be made conditional. +

    There is also a conflict filter that can be accessed through each plugin's menu. + +

    Customising LOOT's Results

    @@ -296,20 +292,7 @@ h3{

    Troubleshooting

    -

    If LOOT encounters a problem at any point, it should provide an error message, either in a dialog (as is generally the case) or in its report (as for errors encountered during the sorting process). If LOOT unexpectedly crashes, or you experience a problem for which no error message is given, please report the crash or problem to an official LOOT thread (see Contributing To LOOT), so that it can be fixed. -

    If the information below does not help you to solve any problems you are experiencing, please seek further support in one of the official LOOT threads. -

    There are a few general reasons why LOOT may fail to function correctly. Check if any of the symptoms listed below fit your issue. -

    -
    LOOT ran without any errors, but the load order hasn't changed to match what LOOT has in its report. -
    Make sure that you aren't using another utility to lock your load order. -
    If you're sorting for Skyrim, make sure that you haven't replaced or renamed your TESV.exe, as this interferes with LOOT's ability to decide how to set the load order. -
    Some plugins have the wrong or no version number given in LOOT's report. -
    No solution. -
    A game is installed, but LOOT cannot detect it. -
    The game's Registry entry is missing. This happens to a lot of people, because Steam likes to remove it whenever the game is updated or its game cache is verified. Run the game's launcher to add the Registry entry back again. -
    There are no line breaks in plugins.txt or loadorder.txt when they are opened in Notepad. -
    There probably are LF line breaks, but Notepad only recognises CRLF line breaks. It doesn't make any difference to the game. -
    +

    If you encounter an issue, check the Frequently Asked Questions wiki page in case a solution is available there. If no solution for your problem is listed there, please seek further support in an official LOOT thread (see Contributing To LOOT).

    Contributing To LOOT

    @@ -372,7 +355,7 @@ To translate the LOOT application:
  • Finnish translation: 3ventic
  • Beta testing: Too many to list, thank you all! -

    LOOT is written in C++ and makes use of the Alphanum, Boost, libespm, libgit2, libloadorder, wxWidgets and yaml-cpp libraries. LOOT's reports are written in HTML5/CSS3/Javascript and make use of Polyfill.js and RequireJS. Copyright license information for all these may be found here. +

    LOOT is written in C++, HTML5, CSS3 and JavaScript, and uses the Alphanum, Boost, Marked, libespm, libgit2, libloadorder, RequireJS and yaml-cpp libraries, the Chromium Embedded Framework, and the FontAwesome icon font. Copyright license information for all these may be found here.

    License

    LOOT is distributed under the GNU General Public License v3.0, aside from the documentation, which is distributed under the GNU Free Documentation License v1.3. The full texts of the licenses are included with LOOT in the accompanying GNU GPL v3.txt and GNU FDL v1.3.txt files. From a6821ced8cca8c54c5c3a11bff43cfc692db02d0 Mon Sep 17 00:00:00 2001 From: WrinklyNinja Date: Wed, 27 Aug 2014 17:31:26 +0100 Subject: [PATCH 22/82] Updated the smaller readme sections. The following are now done: * Installation & Uninstallation * Troubleshooting * Contributing To LOOT * Translating LOOT * Credits * License * Appendices --- docs/LOOT Readme.html | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/docs/LOOT Readme.html b/docs/LOOT Readme.html index fa0d048e..2cc0257e 100644 --- a/docs/LOOT Readme.html +++ b/docs/LOOT Readme.html @@ -300,12 +300,10 @@ h3{

    Otherwise, general discussion takes place in LOOT's official forum threads. These are linked to at the bottom of LOOT's homepage. -

    If you want to submit metadata, the easiest way to do so is to add the metadata to your own LOOT install (either during sorting or in the Metadata Editor), and use the Copy Metadata As Text feature to easily get it in a form that you can then edit into a masterlist on GitHub or post in the official forum threads. +

    If you want to submit metadata, the easiest way to do so is to add the metadata to your own LOOT install, then use the Copy Metadata As Text feature to easily get it in a form that you can then edit into a masterlist on GitHub or post in the official forum threads.

    Information on dirty plugins is very welcome, but for such information to be useful we require at least the filename and the CRC of the dirty plugin. The CRC may be calculated using Wrye Bash or 7-zip, with other sources being unverified as correct. In the case of 7-zip, the CRC checksum for data is the one required. In addition to the CRC, the number of records removed (the ITM count) and/or undeleted (the UDR count) are also welcome. -

    -

    Translating LOOT

    LOOT supports translation into other languages, with the following limitations: @@ -327,16 +325,14 @@ To translate the LOOT application:

  • If you are starting a new translation, select File->New catalogue from POT file... and choose the template file at resources/l10n/template.pot. In the Catalog properties dialog, just click OK without changing anything.
  • If you are updating a previous translation, open in Poedit the loot.po translation file in the relevant subdirectory of resources/l10n, then select Catalogue->Update from POT file... and choose the template file you downloaded. Click OK in the Update summary dialog.
  • Edit the translation file to add or update translations of the programs' text. Strings that were added since the last translation are displayed in bold and dark blue, and strings you have edited the translations of are marked with a star to the left of their source text in the main list. -

    Some languages may use different words or phrases for different contexts where only one word or phrase may be used for all contexts in English. While no contextual information is supplied to translators by default, it can be added on request. To request the addition of contextual information to a text string, contact WrinklyNinja, quoting the structure that contains the string for which you are requesting contextual information. +

    Some languages may use different words or phrases for different contexts where only one word or phrase may be used for all contexts in English. While no contextual information is supplied to translators by default, it can be added on request. To request the addition of contextual information to a text string, create an issue for your request in LOOT's issue tracker, quoting the structure that contains the string for which you are requesting contextual information.

    Some strings to be translated may contain special characters. Different types of special character that may be encountered are:

    • Backslashes \. Backslashes must be escaped using another backslash, so if you wanted to display a single backslash \, you would put \\ in your translated string.
    • Double-quotation marks ". Double-quotation marks must be preceded by a backslash, ie. \", or LOOT will crash when it tries to display the string. -
    • New line characters \n. Do not change the position of these characters relative to the surrounding text, they are responsible for creating new lines. -
    • Words containing an ampersand &. If a string contains a word that begins with or includes an ampersand, the string is for a menu item and the ampersand is a symbol placed before a specific letter and used to show which keyboard key can be used to select that menu item. The ampersand can be moved to be placed before a more appropriate letter in the translated text.
    • Formatting placeholders. Placeholders are used so that LOOT can substitute text or numbers that are generated at runtime into pre-made strings. They appear as a number surrounded by percentage signs, eg. %1%. If formatting placeholders are used in the untranslated string, they must all be present in the translated string, or LOOT will crash when it tries to display the translated string. Placeholders can be moved around so that the sentence makes grammatical sense in the target language.
    -
  • Save the translation file with the filename loot.po in a location of your choosing. +
  • Save the translation file with the filename loot.po in resources/l10n/<locale>/LC_MESSAGES/, where <locale> is your language's locale code. @@ -346,13 +342,17 @@ To translate the LOOT application:

    In addition, the following are credited with application-related support:

    • Icon: jonwd7 -
    • Polish translation: Łukasz Niemczyk -
    • Chinese translation: bluesky404 -
    • French translation: Kaos -
    • Spanish translation: Sharlikran -
    • Russian translation: Tokc.D.K. -
    • Brazilian Portuguese translation: Kassane -
    • Finnish translation: 3ventic +
    • Translations: +
        +
      1. Brazilian Portuguese: Kassane +
      2. Chinese: bluesky404 +
      3. Finnish: 3ventic +
      4. French: Kaos +
      5. German: lpradel +
      6. Polish: Łukasz Niemczyk +
      7. Russian: Tokc.D.K. +
      8. Spanish: Sharlikran +
    • Beta testing: Too many to list, thank you all!

    LOOT is written in C++, HTML5, CSS3 and JavaScript, and uses the Alphanum, Boost, Marked, libespm, libgit2, libloadorder, RequireJS and yaml-cpp libraries, the Chromium Embedded Framework, and the FontAwesome icon font. Copyright license information for all these may be found here. From 1c5ba077e0deb1af25a5085aa6ed268a2f2600a9 Mon Sep 17 00:00:00 2001 From: WrinklyNinja Date: Thu, 28 Aug 2014 21:51:44 +0100 Subject: [PATCH 23/82] Debug logging control is now a toggle only. Closes #263. This is a breaking change for previous alpha users. --- resources/report/js/script.js | 4 ++-- resources/report/report.html | 10 ++-------- src/gui/app.cpp | 36 ++++++++++++++--------------------- 3 files changed, 18 insertions(+), 32 deletions(-) diff --git a/resources/report/js/script.js b/resources/report/js/script.js index c541a18c..2f7f5bae 100644 --- a/resources/report/js/script.js +++ b/resources/report/js/script.js @@ -196,7 +196,7 @@ var loot = { gameSelect.value = this.settings.game; document.getElementById('languageSelect').value = this.settings.language; - document.getElementById('debugVerbositySelect').value = this.settings.debugVerbosity; + document.getElementById('enableDebugLogging').checked = this.settings.enableDebugLogging; document.getElementById('updateMasterlist').checked = this.settings.updateMasterlist; this.updateEnabledGames(); @@ -1032,7 +1032,7 @@ function closeSettingsDialog(evt) { if (evt.target.classList.contains('accept')) { /* Update the JS variable values. */ var settings = { - debugVerbosity: document.getElementById('debugVerbositySelect').value, + enableDebugLogging: document.getElementById('enableDebugLogging').checked, game: document.getElementById('defaultGameSelect').value, games: document.getElementById('gameTable').getRowsData(false), language: document.getElementById('languageSelect').value, diff --git a/resources/report/report.html b/resources/report/report.html index 3d62a37c..f3af7254 100644 --- a/resources/report/report.html +++ b/resources/report/report.html @@ -541,13 +541,8 @@ along with LOOT. If not, see <http://www.gnu.org/licenses/>.
    - - +

    +

    NameBase GameLOOT FolderMaster FileMasterlist Repository URLMasterlist Repository BranchInstall PathInstall Path Registry Key @@ -555,7 +550,6 @@ along with LOOT. If not, see <http://www.gnu.org/licenses/>.
    Add new row...
    -

    Language changes will be applied after LOOT is restarted.


    diff --git a/src/gui/app.cpp b/src/gui/app.cpp index b2b29b74..471a48e6 100644 --- a/src/gui/app.cpp +++ b/src/gui/app.cpp @@ -160,29 +160,21 @@ namespace loot { boost::log::keywords::file_name = g_path_log.string().c_str(), boost::log::keywords::auto_flush = true, boost::log::keywords::format = ( - boost::log::expressions::stream - << "[" << boost::log::expressions::format_date_time< boost::posix_time::ptime >("TimeStamp", "%H:%M:%S") << "]" - << " [" << boost::log::trivial::severity << "]: " - << boost::log::expressions::smessage + boost::log::expressions::stream + << "[" << boost::log::expressions::format_date_time< boost::posix_time::ptime >("TimeStamp", "%H:%M:%S") << "]" + << " [" << boost::log::trivial::severity << "]: " + << boost::log::expressions::smessage ) - ); + ); boost::log::add_common_attributes(); - unsigned int verbosity; - if (_settings["debugVerbosity"]) { - verbosity = _settings["debugVerbosity"].as(); + bool enableDebugLogging = false; + if (_settings["enableDebugLogging"]) { + enableDebugLogging = _settings["enableDebugLogging"].as(); } - if (verbosity == 0) - boost::log::core::get()->set_logging_enabled(false); - else { + if (enableDebugLogging) boost::log::core::get()->set_logging_enabled(true); - - if (verbosity == 1) - boost::log::core::get()->set_filter(boost::log::trivial::severity >= boost::log::trivial::warning); //Log all warnings, errors and fatals. - else if (verbosity == 2) - boost::log::core::get()->set_filter(boost::log::trivial::severity >= boost::log::trivial::debug); //Log debugs, infos, warnings, errors and fatals. - else - boost::log::core::get()->set_filter(boost::log::trivial::severity >= boost::log::trivial::trace); //Log everything. - } + else + boost::log::core::get()->set_logging_enabled(false); BOOST_LOG_TRIVIAL(info) << "LOOT Version: " << g_version_major << "." << g_version_minor << "." << g_version_patch; // The CEF debug log is appended to, not overwritten, so it gets really long. @@ -350,10 +342,10 @@ namespace loot { else return false; } - if (!_settings["debugVerbosity"]) { + if (!_settings["enableDebugLogging"]) { if (_settings["Debug Verbosity"]) { // Conversion from 0.6 key. - _settings["debugVerbosity"] = _settings["Debug Verbosity"]; + _settings["enableDebugLogging"] = (_settings["Debug Verbosity"].as() > 0); _settings.remove("Debug Verbosity"); } else @@ -398,7 +390,7 @@ namespace loot { root["language"] = "en"; root["game"] = "auto"; root["lastGame"] = "auto"; - root["debugVerbosity"] = 0; + root["enableDebugLogging"] = false; root["updateMasterlist"] = true; std::vector games; From 26ed75d66aa023e11765179e32340582caa5085a Mon Sep 17 00:00:00 2001 From: WrinklyNinja Date: Thu, 28 Aug 2014 21:55:47 +0100 Subject: [PATCH 24/82] Toggling debug logging now has immediate effect. Fixes #256. --- src/gui/handler.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/gui/handler.cpp b/src/gui/handler.cpp index c8ca1f42..457257f7 100644 --- a/src/gui/handler.cpp +++ b/src/gui/handler.cpp @@ -264,6 +264,12 @@ namespace loot { g_app_state.UpdateGames(games); + // Also enable/disable debug logging as required. + if (request["args"][0]["enableDebugLogging"].as()) + boost::log::core::get()->set_logging_enabled(true); + else + boost::log::core::get()->set_logging_enabled(false); + // Now send back the new list of installed games to the UI. callback->Success(GetInstalledGames()); return true; From adf1c3295b77b3e6e06ac9273214aaa21e6d6479 Mon Sep 17 00:00:00 2001 From: WrinklyNinja Date: Thu, 28 Aug 2014 22:34:06 +0100 Subject: [PATCH 25/82] Masterlist update now only tests condition parsing. Instead of evaluating the conditions, and modifying the data stored in the masterlist object. This will probably also speed up masterlist updating a little. Fixes #257. --- src/backend/git.cpp | 9 +++---- src/backend/metadata.cpp | 58 +++++++++++++++++++++++++++++++++++++--- src/backend/metadata.h | 10 ++++--- src/backend/parsers.h | 46 ++++++++++++++++++------------- 4 files changed, 90 insertions(+), 33 deletions(-) diff --git a/src/backend/git.cpp b/src/backend/git.cpp index 6eb58881..85437b62 100644 --- a/src/backend/git.cpp +++ b/src/backend/git.cpp @@ -424,17 +424,14 @@ namespace loot { try { this->MetadataList::Load(game.MasterlistPath()); - unordered_set tempSet; for (auto &plugin : plugins) { - tempSet.insert(Plugin(plugin).EvalAllConditions(game, language)); + plugin.ParseAllConditions(game); } - plugins = tempSet; for (auto &plugin : regexPlugins) { - plugin.EvalAllConditions(game, language); + plugin.ParseAllConditions(game); } - for (auto &message: messages) { - message.EvalCondition(game, language); + message.ParseCondition(game); } parsingFailed = false; diff --git a/src/backend/metadata.cpp b/src/backend/metadata.cpp index 1a0a816f..0ca2e724 100644 --- a/src/backend/metadata.cpp +++ b/src/backend/metadata.cpp @@ -118,7 +118,7 @@ namespace loot { return _condition; } - bool ConditionStruct::EvalCondition(loot::Game& game) const { + bool ConditionStruct::EvalCondition(Game& game) const { if (_condition.empty()) return true; @@ -128,12 +128,11 @@ namespace loot { if (it != game.conditionCache.end()) return it->second; - condition_grammar grammar; + condition_grammar grammar(game, false); boost::spirit::qi::space_type skipper; std::string::const_iterator begin, end; bool eval; - grammar.SetGame(game); begin = _condition.begin(); end = _condition.end(); @@ -155,6 +154,39 @@ namespace loot { return eval; } + void ConditionStruct::ParseCondition(Game& game) const { + if (_condition.empty()) + return; + + BOOST_LOG_TRIVIAL(trace) << "Testing condition syntax: " << _condition; + + // If the same condition string has already been evaluated, it must be written correctly. + unordered_map::const_iterator it = game.conditionCache.find(boost::locale::to_lower(_condition)); + if (it != game.conditionCache.end()) + return; + + condition_grammar grammar(game, true); + boost::spirit::qi::space_type skipper; + std::string::const_iterator begin, end; + + begin = _condition.begin(); + end = _condition.end(); + + bool r; + try { + r = boost::spirit::qi::phrase_parse(begin, end, grammar, skipper); + } + catch (std::exception& e) { + BOOST_LOG_TRIVIAL(error) << "Failed to parse condition \"" << _condition << "\": " << e.what(); + throw loot::error(loot::error::condition_eval_fail, (boost::format(lc::translate("Failed to parse condition \"%1%\": %2%")) % _condition % e.what()).str()); + } + + if (!r || begin != end) { + BOOST_LOG_TRIVIAL(error) << "Failed to parse condition \"" << _condition << "\"."; + throw loot::error(loot::error::condition_eval_fail, (boost::format(lc::translate("Failed to parse condition \"%1%\".")) % _condition).str()); + } + } + MessageContent::MessageContent() : _language(Language::english) {} MessageContent::MessageContent(const std::string& str, const unsigned int language) : _str(str), _language(language) {} @@ -574,7 +606,7 @@ namespace loot { _dirtyInfo = dirtyInfo; } - Plugin& Plugin::EvalAllConditions(loot::Game& game, const unsigned int language) { + Plugin& Plugin::EvalAllConditions(Game& game, const unsigned int language) { for (auto it = loadAfter.begin(); it != loadAfter.end();) { if (!it->EvalCondition(game)) loadAfter.erase(it++); @@ -634,6 +666,24 @@ namespace loot { return *this; } + void Plugin::ParseAllConditions(Game& game) const { + for (const File& file : loadAfter) { + file.ParseCondition(game); + } + for (const File& file : requirements) { + file.ParseCondition(game); + } + for (const File& file : incompatibilities) { + file.ParseCondition(game); + } + for (const Message& message : messages) { + message.ParseCondition(game); + } + for (const Tag& tag : tags) { + tag.ParseCondition(game); + } + } + bool Plugin::HasNameOnly() const { return !IsPriorityExplicit() && loadAfter.empty() && requirements.empty() && incompatibilities.empty() && messages.empty() && tags.empty() && _dirtyInfo.empty(); } diff --git a/src/backend/metadata.h b/src/backend/metadata.h index 1bf040c2..03efa274 100644 --- a/src/backend/metadata.h +++ b/src/backend/metadata.h @@ -83,7 +83,8 @@ namespace loot { ConditionStruct(const std::string& condition); bool IsConditional() const; - bool EvalCondition(loot::Game& game) const; + bool EvalCondition(Game& game) const; + void ParseCondition(Game& game) const; // Throws error on parsing failure. std::string Condition() const; private: @@ -116,7 +117,7 @@ namespace loot { bool operator < (const Message& rhs) const; bool operator == (const Message& rhs) const; - bool EvalCondition(loot::Game& game, const unsigned int language); + bool EvalCondition(Game& game, const unsigned int language); unsigned int Type() const; std::vector Content() const; @@ -166,7 +167,7 @@ namespace loot { public: Plugin(); Plugin(const std::string& name); - Plugin(loot::Game& game, const std::string& name, const bool headerOnly); + Plugin(Game& game, const std::string& name, const bool headerOnly); //Merges from the given plugin into this one, unless there is already equal metadata present. //For 'enabled' and 'priority' metadata, use the given plugin's values, but if the 'priority' user value is zero, ignore it. @@ -204,7 +205,8 @@ namespace loot { void Tags(const std::set& tags); void DirtyInfo(const std::set& info); - Plugin& EvalAllConditions(loot::Game& game, const unsigned int language); + Plugin& EvalAllConditions(Game& game, const unsigned int language); + void ParseAllConditions(Game& game) const; bool HasNameOnly() const; bool IsRegexPlugin() const; bool LoadsBSA(const Game& game) const; diff --git a/src/backend/parsers.h b/src/backend/parsers.h index bd93daed..27105b25 100644 --- a/src/backend/parsers.h +++ b/src/backend/parsers.h @@ -400,7 +400,7 @@ namespace loot { template class condition_grammar : public qi::grammar { public: - condition_grammar() : condition_grammar::base_type(expression, "condition grammar") { + condition_grammar(Game& game, bool parseOnly) : condition_grammar::base_type(expression, "condition grammar"), _game(game), _parseOnly(parseOnly) { expression = compound [qi::labels::_val = qi::labels::_1] @@ -468,19 +468,18 @@ namespace loot { qi::on_error(invalidPathChars, phoenix::bind(&condition_grammar::SyntaxError, this, qi::labels::_1, qi::labels::_2, qi::labels::_3, qi::labels::_4)); } - void SetGame(loot::Game& g) { - game = &g; - } - private: qi::rule expression, compound, condition, function; qi::rule quotedStr, filePath, comparator; qi::rule invalidPathChars; - loot::Game * game; + Game& _game; + bool _parseOnly; //Eval's exact paths. Check for files and ghosted plugins. void CheckFile(bool& result, const std::string& file) { + if (_parseOnly) + return; BOOST_LOG_TRIVIAL(trace) << "Checking to see if the file \"" << file << "\" exists."; @@ -495,9 +494,9 @@ namespace loot { } if (IsPlugin(file)) - result = boost::filesystem::exists(game->DataPath() / file) || boost::filesystem::exists(game->DataPath() / (file + ".ghost")); + result = boost::filesystem::exists(_game.DataPath() / file) || boost::filesystem::exists(_game.DataPath() / (file + ".ghost")); else - result = boost::filesystem::exists(game->DataPath() / file); + result = boost::filesystem::exists(_game.DataPath() / file); if (result) BOOST_LOG_TRIVIAL(trace) << "The file does exist."; @@ -506,6 +505,8 @@ namespace loot { } void CheckRegex(bool& result, const std::string& regexStr) { + if (_parseOnly) + return; result = false; //Can't support a regex string where all path components may be regex, since this could //lead to massive scanning if an unfortunately-named directory is encountered. @@ -549,7 +550,7 @@ namespace loot { //Now we have a valid parent path and a regex filename. Check that //the parent path exists and is a directory. - boost::filesystem::path parent_path = game->DataPath() / parent; + boost::filesystem::path parent_path = _game.DataPath() / parent; if (!boost::filesystem::exists(parent_path) || !boost::filesystem::is_directory(parent_path)) { BOOST_LOG_TRIVIAL(trace) << "The path \"" << parent_path << "\" does not exist or is not a directory."; return; @@ -573,6 +574,8 @@ namespace loot { } void CheckSum(bool& result, const std::string& file, const uint32_t checksum) { + if (_parseOnly) + return; BOOST_LOG_TRIVIAL(trace) << "Checking the CRC of the file \"" << file << "\"."; @@ -582,29 +585,31 @@ namespace loot { } uint32_t crc; - unordered_map::iterator it = game->crcCache.find(boost::to_lower_copy(file)); + unordered_map::iterator it = _game.crcCache.find(boost::to_lower_copy(file)); - if (it != game->crcCache.end()) + if (it != _game.crcCache.end()) crc = it->second; else { if (file == "LOOT") crc = GetCrc32(boost::filesystem::absolute("LOOT.exe")); - if (boost::filesystem::exists(game->DataPath() / file)) - crc = GetCrc32(game->DataPath() / file); - else if (IsPlugin(file) && boost::filesystem::exists(game->DataPath() / (file + ".ghost"))) - crc = GetCrc32(game->DataPath() / (file + ".ghost")); + if (boost::filesystem::exists(_game.DataPath() / file)) + crc = GetCrc32(_game.DataPath() / file); + else if (IsPlugin(file) && boost::filesystem::exists(_game.DataPath() / (file + ".ghost"))) + crc = GetCrc32(_game.DataPath() / (file + ".ghost")); else { result = false; return; } - game->crcCache.emplace(boost::to_lower_copy(file), crc); + _game.crcCache.emplace(boost::to_lower_copy(file), crc); } result = checksum == crc; } void CheckVersion(bool& result, const std::string& file, const std::string& version, const std::string& comparator) { + if (_parseOnly) + return; BOOST_LOG_TRIVIAL(trace) << "Checking version of file \"" << file << "\"."; @@ -621,10 +626,10 @@ namespace loot { if (file == "LOOT") trueVersion = Version(boost::filesystem::absolute("LOOT.exe")); else if (IsPlugin(file)) { - Plugin plugin(*game, file, true); + Plugin plugin(_game, file, true); trueVersion = Version(plugin.Version()); } else - trueVersion = Version(game->DataPath() / file); + trueVersion = Version(_game.DataPath() / file); BOOST_LOG_TRIVIAL(trace) << "Version extracted: " << trueVersion.AsString(); @@ -640,10 +645,13 @@ namespace loot { } void CheckActive(bool& result, const std::string& file) { + if (_parseOnly) + return; + if (file == "LOOT") result = false; else - result = game->IsActive(file); + result = _game.IsActive(file); BOOST_LOG_TRIVIAL(trace) << "Active check result: " << result; } From f159d005948beaa427e21ad5d2335b9e5163e8bb Mon Sep 17 00:00:00 2001 From: WrinklyNinja Date: Thu, 28 Aug 2014 22:55:30 +0100 Subject: [PATCH 26/82] Added more progress dialog feedback. Conflict filtering no longer blocks the UI and has progress feedback, and sorting and masterlist updating now have progress feedback. Fixes #262. --- resources/report/js/script.js | 5 +++++ src/gui/handler.cpp | 28 ++++++++++++++++++---------- src/gui/handler.h | 6 +++--- 3 files changed, 26 insertions(+), 13 deletions(-) diff --git a/resources/report/js/script.js b/resources/report/js/script.js index 2f7f5bae..0f60aaf6 100644 --- a/resources/report/js/script.js +++ b/resources/report/js/script.js @@ -432,6 +432,9 @@ function getConflictingPluginsFromFilter() { ] }); + updateProgressDialog('Checking if plugins have been loaded...'); + openProgressDialog(); + return loot.query(request).then(JSON.parse).then(function(result){ if (result) { /* Filter everything but the plugin itself if there are no @@ -449,8 +452,10 @@ function getConflictingPluginsFromFilter() { } } } + closeProgressDialog(); return conflicts; } + closeProgressDialog(); return [ conflictsPlugin ]; }).catch(processCefError); } diff --git a/src/gui/handler.cpp b/src/gui/handler.cpp index 457257f7..2a7b63d0 100644 --- a/src/gui/handler.cpp +++ b/src/gui/handler.cpp @@ -154,10 +154,10 @@ namespace loot { return true; } else if (request == "updateMasterlist") { - return CefPostTask(TID_FILE, base::Bind(&Handler::UpdateMasterlist, base::Unretained(this), callback)); + return CefPostTask(TID_FILE, base::Bind(&Handler::UpdateMasterlist, base::Unretained(this), frame, callback)); } else if (request == "sortPlugins") { - return CefPostTask(TID_FILE, base::Bind(&Handler::SortPlugins, base::Unretained(this), callback)); + return CefPostTask(TID_FILE, base::Bind(&Handler::SortPlugins, base::Unretained(this), frame, callback)); } else if (request == "getInitErrors") { YAML::Node node(g_app_state.InitErrors()); @@ -223,7 +223,7 @@ namespace loot { } else if (requestName == "getConflictingPlugins") { // Has one arg, which is the name of the plugin to get conflicts for. - callback->Success(GetConflictingPlugins(request["args"][0].as())); + CefPostTask(TID_FILE, base::Bind(&Handler::GetConflictingPlugins, base::Unretained(this), request["args"][0].as(), frame, callback)); return true; } else if (requestName == "copyMetadata") { @@ -333,16 +333,19 @@ namespace loot { browser->GetHost()->Find(0, search, true, false, false); } - std::string Handler::GetConflictingPlugins(const std::string& pluginName) { + void Handler::GetConflictingPlugins(const std::string& pluginName, CefRefPtr frame, CefRefPtr callback) { BOOST_LOG_TRIVIAL(debug) << "Searching for plugins that conflict with " << pluginName; auto pluginIt = g_app_state.CurrentGame().plugins.find(boost::locale::to_lower(pluginName)); // Checking for FormID overlap will only work if the plugins have been loaded, so check if // the plugins have been fully loaded, and if not load all plugins. - if (!g_app_state.CurrentGame().HasBeenLoaded()) + if (!g_app_state.CurrentGame().HasBeenLoaded()) { + SendProgressUpdate(frame, "Loading plugin contents..."); g_app_state.CurrentGame().LoadPlugins(false); + } + SendProgressUpdate(frame, "Checking for conflicting plugins..."); YAML::Node node; for (const auto& pluginPair : g_app_state.CurrentGame().plugins) { YAML::Node pluginNode; @@ -360,9 +363,9 @@ namespace loot { } if (node.size() > 0) - return JSON::stringify(node); + callback->Success(JSON::stringify(node)); else - return "null"; + callback->Success("null"); } void Handler::CopyMetadata(const std::string& pluginName) { @@ -727,7 +730,7 @@ namespace loot { } } - void Handler::UpdateMasterlist(CefRefPtr callback) { + void Handler::UpdateMasterlist(CefRefPtr frame, CefRefPtr callback) { try { BOOST_LOG_TRIVIAL(debug) << "Updating and parsing masterlist."; @@ -742,6 +745,7 @@ namespace loot { // Update / parse masterlist. bool wasChanged = true; try { + SendProgressUpdate(frame, "Updating and parsing masterlist..."); wasChanged = g_app_state.CurrentGame().masterlist.Load(g_app_state.CurrentGame(), language); } catch (loot::error &e) { @@ -757,6 +761,7 @@ namespace loot { } // Now regenerate the JS-side masterlist data if the masterlist was changed. + SendProgressUpdate(frame, "Regenerating displayed content..."); if (wasChanged) { // The data structure is to be set as 'loot.game'. YAML::Node gameNode; @@ -853,7 +858,7 @@ namespace loot { return "[]"; } - void Handler::SortPlugins(CefRefPtr callback) { + void Handler::SortPlugins(CefRefPtr frame, CefRefPtr callback) { //Set language. unsigned int language; if (g_app_state.GetSettings()["language"]) @@ -863,10 +868,13 @@ namespace loot { BOOST_LOG_TRIVIAL(info) << "Using message language: " << Language(language).Name(); // Always reload all the plugins. + SendProgressUpdate(frame, "Loading plugin contents..."); g_app_state.CurrentGame().LoadPlugins(false); //Sort plugins into their load order. - list plugins = g_app_state.CurrentGame().Sort(language, [](const string& message){}); + list plugins = g_app_state.CurrentGame().Sort(language, [this, frame](const string& message){ + this->SendProgressUpdate(frame, message); + }); YAML::Node node; for (const auto &plugin : plugins) { diff --git a/src/gui/handler.h b/src/gui/handler.h index df42678c..9c47c0c6 100644 --- a/src/gui/handler.h +++ b/src/gui/handler.h @@ -57,9 +57,9 @@ namespace loot { std::string GetGameTypes(); std::string GetInstalledGames(); void GetGameData(CefRefPtr frame, CefRefPtr callback); - void UpdateMasterlist(CefRefPtr callback); + void UpdateMasterlist(CefRefPtr frame, CefRefPtr callback); std::string ClearAllMetadata(); - void SortPlugins(CefRefPtr callback); + void SortPlugins(CefRefPtr frame, CefRefPtr callback); // Handle queries with input arguments. bool HandleComplexQuery(CefRefPtr browser, @@ -68,7 +68,7 @@ namespace loot { CefRefPtr callback); void Find(CefRefPtr browser, const std::string& search); - std::string GetConflictingPlugins(const std::string& pluginName); + void GetConflictingPlugins(const std::string& pluginName, CefRefPtr frame, CefRefPtr callback); void CopyMetadata(const std::string& pluginName); std::string ClearPluginMetadata(const std::string& pluginName); void SaveFilterState(const std::string& filterId, const std::string& value); From 7839d18d8e202970bce7ca565e8d39afa7fe7a2b Mon Sep 17 00:00:00 2001 From: WrinklyNinja Date: Fri, 29 Aug 2014 11:40:41 +0100 Subject: [PATCH 27/82] Updated plugin description Bash Tag extraction. Now uses regex matching, which is easier to read and shouldn't provide any real performance hit. Also added a few more debug logging statements, and tidied up version matching too. --- src/backend/helpers.cpp | 5 ++++- src/backend/helpers.h | 5 ++++- src/backend/metadata.cpp | 47 ++++++++++++---------------------------- src/gui/handler.cpp | 1 + 4 files changed, 23 insertions(+), 35 deletions(-) diff --git a/src/backend/helpers.cpp b/src/backend/helpers.cpp index 7058c605..10db6aa0 100644 --- a/src/backend/helpers.cpp +++ b/src/backend/helpers.cpp @@ -107,7 +107,7 @@ namespace loot { /// Array used to try each of the expressions defined above using /// an iteration for each of them. - regex version_checks[7] = { + const regex version_checks[7] = { regex(regex1, regex::ECMAScript | regex::icase), regex(regex2, regex::ECMAScript | regex::icase), regex(regex3, regex::ECMAScript | regex::icase), @@ -117,6 +117,9 @@ namespace loot { regex(regex7, regex::ECMAScript | regex::icase) }; + // A regular expression for finding Bash Tags in plugin descriptions. + const regex bash_tag_check("\\{\\{BASH:(?:[ ]*([-A-Za-z.]+)[ ]*,)+[ ]*\\}\\}", regex::ECMAScript | regex::icase); + ////////////////////////////////////////////////////////////////////////// // Helper functions ////////////////////////////////////////////////////////////////////////// diff --git a/src/backend/helpers.h b/src/backend/helpers.h index 61c2b542..17cb3bcb 100644 --- a/src/backend/helpers.h +++ b/src/backend/helpers.h @@ -36,7 +36,10 @@ namespace loot { /// Array used to try each of the expressions defined using /// an iteration for each of them. - extern std::regex version_checks[7]; + extern const std::regex version_checks[7]; + + // A regular expression for finding Bash Tags in plugin descriptions. + extern const std::regex bash_tag_check; ////////////////////////////////////////////////////////////////////////// // Helper functions diff --git a/src/backend/metadata.cpp b/src/backend/metadata.cpp index 0ca2e724..e969de8b 100644 --- a/src/backend/metadata.cpp +++ b/src/backend/metadata.cpp @@ -400,47 +400,28 @@ namespace loot { delete file; - string::const_iterator begin, end; - begin = text.begin(); - end = text.end(); - BOOST_LOG_TRIVIAL(trace) << name << ": " << "Attempting to read the version from the description."; for (int j = 0; j < 7 && version.empty(); j++) { smatch what; - while (regex_search(begin, end, what, version_checks[j])) { - if (what.empty()) - continue; - - ssub_match match = what[1]; - if (!match.matched) - continue; - - version = boost::trim_copy(string(match.first, match.second)); + if (regex_search(text, what, version_checks[j])) { + //Use the first sub-expression match. + version = string(what[1].first, what[1].second); break; } } - BOOST_LOG_TRIVIAL(trace) << name << ": " << "Attempting to extract Bash Tags from the description."; - size_t pos1 = text.find("{{BASH:"); - if (pos1 == string::npos || pos1 + 7 == text.length()) - return; - - pos1 += 7; - - size_t pos2 = text.find("}}", pos1); - if (pos2 == string::npos) - return; - - text = text.substr(pos1, pos2-pos1); - - vector bashTags; - boost::split(bashTags, text, boost::is_any_of(",")); - - for (auto &tag: bashTags) { - boost::trim(tag); - BOOST_LOG_TRIVIAL(trace) << name << ": " << "Extracted Bash Tag: " << tag; - tags.insert(Tag(tag)); + smatch results; + if (regex_search(text, results, bash_tag_check)) { + // Regex requires there to be at least one sub-expression match, + // so skip the first (which is the full expression. + for (size_t i = 1; i < results.size(); ++i) { + // Tags in the description must be addition tags, because there's + // nowhere else to remove them from. + auto tag = tags.insert(Tag(string(results[i].first, results[i].second))); + BOOST_LOG_TRIVIAL(trace) << name << ": " << "Extracted Bash Tag: " << tag.first->Name(); + } } + BOOST_LOG_TRIVIAL(trace) << name << ": " << "Plugin loading complete."; } void Plugin::MergeMetadata(const Plugin& plugin) { diff --git a/src/gui/handler.cpp b/src/gui/handler.cpp index 2a7b63d0..4a4d80b2 100644 --- a/src/gui/handler.cpp +++ b/src/gui/handler.cpp @@ -859,6 +859,7 @@ namespace loot { } void Handler::SortPlugins(CefRefPtr frame, CefRefPtr callback) { + BOOST_LOG_TRIVIAL(info) << "Beginning sorting operation."; //Set language. unsigned int language; if (g_app_state.GetSettings()["language"]) From a87f32fc8501764f2110e1e21e24e41ec607cdbd Mon Sep 17 00:00:00 2001 From: WrinklyNinja Date: Fri, 29 Aug 2014 11:44:00 +0100 Subject: [PATCH 28/82] Removed unnecessary check from version loop. Also unsigned counters let me sleep easier at night. --- src/backend/metadata.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/backend/metadata.cpp b/src/backend/metadata.cpp index e969de8b..5867d288 100644 --- a/src/backend/metadata.cpp +++ b/src/backend/metadata.cpp @@ -401,9 +401,9 @@ namespace loot { delete file; BOOST_LOG_TRIVIAL(trace) << name << ": " << "Attempting to read the version from the description."; - for (int j = 0; j < 7 && version.empty(); j++) { + for (size_t i = 0; i < 7; ++i) { smatch what; - if (regex_search(text, what, version_checks[j])) { + if (regex_search(text, what, version_checks[i])) { //Use the first sub-expression match. version = string(what[1].first, what[1].second); break; From 1f4d5e4345705765f10754a9ed184e19e00dffc7 Mon Sep 17 00:00:00 2001 From: WrinklyNinja Date: Fri, 29 Aug 2014 12:54:39 +0100 Subject: [PATCH 29/82] No need for a bidirectional graph. --- src/backend/graph.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/backend/graph.h b/src/backend/graph.h index cbd0d340..76ac70b5 100644 --- a/src/backend/graph.h +++ b/src/backend/graph.h @@ -34,7 +34,7 @@ namespace loot { - typedef boost::adjacency_list PluginGraph; + typedef boost::adjacency_list PluginGraph; typedef boost::graph_traits::vertex_descriptor vertex_t; typedef boost::graph_traits::vertex_iterator vertex_it; typedef boost::graph_traits::edge_descriptor edge_t; From 6495e3bc234518aaf7924c66fd9e12542e9c465f Mon Sep 17 00:00:00 2001 From: WrinklyNinja Date: Fri, 29 Aug 2014 13:04:01 +0100 Subject: [PATCH 30/82] Added Mod Organiser detection. Closes #264. --- src/gui/app.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/gui/app.cpp b/src/gui/app.cpp index 471a48e6..c38127bc 100644 --- a/src/gui/app.cpp +++ b/src/gui/app.cpp @@ -175,7 +175,16 @@ namespace loot { boost::log::core::get()->set_logging_enabled(true); else boost::log::core::get()->set_logging_enabled(false); + + // Log some useful info. BOOST_LOG_TRIVIAL(info) << "LOOT Version: " << g_version_major << "." << g_version_minor << "." << g_version_patch; +#ifdef _WIN32 + // Check if LOOT is being run through Mod Organiser. + bool runFromMO = GetModuleHandle(ToWinWide("hook.dll").c_str()) != NULL; + if (runFromMO) { + BOOST_LOG_TRIVIAL(info) << "LOOT is being run through Mod Organiser."; + } +#endif // The CEF debug log is appended to, not overwritten, so it gets really long. // Delete the current CEF debug log. From 1fdd430c1cd5830a8058479153523ced13191dcf Mon Sep 17 00:00:00 2001 From: "Frederik \"Freso\" S. Olesen" Date: Fri, 29 Aug 2014 14:36:20 +0200 Subject: [PATCH 31/82] Convert debug setting from 0.7 alpha 1-3. Follow-up to commit 1c5ba077e0deb1af25a5085aa6ed268a2f2600a9 --- src/gui/app.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/gui/app.cpp b/src/gui/app.cpp index c38127bc..957e1d51 100644 --- a/src/gui/app.cpp +++ b/src/gui/app.cpp @@ -357,6 +357,11 @@ namespace loot { _settings["enableDebugLogging"] = (_settings["Debug Verbosity"].as() > 0); _settings.remove("Debug Verbosity"); } + else if (_setting["debugVerbosity"]) { + // Conversion from 0.7 alpha key + _settings["enableDebugLogging"] = (_settings["debugVerbosity"].as() > 0); + _settings.remove("debugVerbosity"); + } else return false; } @@ -413,4 +418,4 @@ namespace loot { return root; } -} \ No newline at end of file +} From 1b26a464183a96d824856c3810e91ce39e301691 Mon Sep 17 00:00:00 2001 From: WrinklyNinja Date: Fri, 29 Aug 2014 13:44:56 +0100 Subject: [PATCH 32/82] Corrected typo in previous pull request. Introduced in 1fdd430c1cd5830a8058479153523ced13191dcf --- src/gui/app.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gui/app.cpp b/src/gui/app.cpp index 957e1d51..1091aa2d 100644 --- a/src/gui/app.cpp +++ b/src/gui/app.cpp @@ -357,7 +357,7 @@ namespace loot { _settings["enableDebugLogging"] = (_settings["Debug Verbosity"].as() > 0); _settings.remove("Debug Verbosity"); } - else if (_setting["debugVerbosity"]) { + else if (_settings["debugVerbosity"]) { // Conversion from 0.7 alpha key _settings["enableDebugLogging"] = (_settings["debugVerbosity"].as() > 0); _settings.remove("debugVerbosity"); From 82e68bda91fd7df4fc65455ab3cfb1866f50bcb9 Mon Sep 17 00:00:00 2001 From: WrinklyNinja Date: Thu, 28 Aug 2014 12:42:14 +0100 Subject: [PATCH 33/82] Added icons for plugin priorities. --- resources/report/js/custom.js | 8 -------- resources/report/js/plugin.js | 17 ++++++++--------- resources/report/js/script.js | 4 ++-- resources/report/report.html | 11 +++++++++-- 4 files changed, 19 insertions(+), 21 deletions(-) diff --git a/resources/report/js/custom.js b/resources/report/js/custom.js index 81bc1a45..bec62942 100644 --- a/resources/report/js/custom.js +++ b/resources/report/js/custom.js @@ -624,15 +624,7 @@ var pluginLIProto = Object.create(HTMLLIElement.prototype, { var template = document.getElementById('pluginLI'); var clone = document.importNode(template.content, true); - this.createShadowRoot().appendChild(clone); - - var name = document.createElement('span'); - name.className = 'name'; - this.appendChild(name); - var priority = document.createElement('span'); - priority.className = 'priority'; - this.appendChild(priority); } }, diff --git a/resources/report/js/plugin.js b/resources/report/js/plugin.js index 6188d20b..1f5caa07 100644 --- a/resources/report/js/plugin.js +++ b/resources/report/js/plugin.js @@ -103,13 +103,11 @@ function Plugin(obj) { } Plugin.prototype.getPriorityString = function() { - var priorityText = 'Priority: ' + this.modPriority + ', Global: '; - if (this.isGlobalPriority) { - priorityText += '✓'; + if (this.modPriority != 0) { + return 'Priority: ' + this.modPriority; } else { - priorityText += '✗'; + return ''; } - return priorityText; } Plugin.prototype.updateCardMessages = function() { @@ -166,12 +164,13 @@ function Plugin(obj) { li.shadowRoot.getElementsByTagName('a')[0].href = '#' + this.id; - li.getElementsByClassName('name')[0].textContent = this.name; - li.getElementsByClassName('priority')[0].textContent = this.getPriorityString(); + li.textContent = this.name; li.setAttribute('data-dummy', this.isDummy); li.setAttribute('data-bsa', this.loadsBSA); li.setAttribute('data-edits', this.userlist != undefined); + li.setAttribute('data-global-priority', this.isGlobalPriority); + li.shadowRoot.getElementsByClassName('hasPriority')[0].title = this.getPriorityString(); document.getElementById('pluginsNav').appendChild(li); } @@ -182,10 +181,10 @@ function Plugin(obj) { change.object.li.setAttribute('data-edits', change.object[change.name] != undefined); change.object.card.setAttribute('data-edits', change.object[change.name] != undefined); } else if (change.name == 'modPriority') { - change.object.li.getElementsByClassName('priority')[0].textContent = change.object.getPriorityString(); + change.object.li.shadowRoot.getElementsByClassName('hasPriority')[0].title = this.getPriorityString(); change.object.card.shadowRoot.getElementById('priorityValue').value = change.object[change.name]; } else if (change.name == 'isGlobalPriority') { - change.object.li.getElementsByClassName('priority')[0].textContent = change.object.getPriorityString(); + change.object.li.shadowRoot.getElementsByClassName('hasPriority')[0].title = this.getPriorityString(); } else if (change.name == 'messages') { change.object.updateCardMessages(); /* For messages, the card's messages need updating, diff --git a/resources/report/js/script.js b/resources/report/js/script.js index 0f60aaf6..1d1fbdc0 100644 --- a/resources/report/js/script.js +++ b/resources/report/js/script.js @@ -735,7 +735,7 @@ function sortUIElements(pluginNames) { /* Also need to move plugin sidebar entry. */ var li; for (var i = 0; i < entries.length; ++i) { - if (entries[i].getElementsByClassName('name')[0].textContent == name) { + if (entries[i].textContent == name) { li = entries[i]; } } @@ -959,7 +959,7 @@ function handlePluginDrop(evt) { } function handlePluginDragStart(evt) { evt.dataTransfer.effectAllowed = 'copy'; - evt.dataTransfer.setData('text/plain', evt.target.getElementsByClassName('name')[0].textContent); + evt.dataTransfer.setData('text/plain', evt.target.textContent); } function handlePluginDragOver(evt) { evt.preventDefault(); diff --git a/resources/report/report.html b/resources/report/report.html index f3af7254..f625b8e2 100644 --- a/resources/report/report.html +++ b/resources/report/report.html @@ -300,6 +300,12 @@ :host([data-edits=false]) .hasUserEdits { visibility: hidden; } + :host([data-global-priority=false]) .hasGlobalPriority { + visibility: hidden; + } + .hasPriority:not([title^=Priority]) { + visibility: hidden; + } a { text-decoration: none; color: black; @@ -308,9 +314,10 @@ + + - - +