diff --git a/README.md b/README.md index 3cd593f4..8137ea3b 100644 --- a/README.md +++ b/README.md @@ -42,6 +42,16 @@ curl -sS https://getcomposer.org/installer | sudo php -- --install-dir=/usr/loca # Load php_gmp extension echo "extension=php_gmp.so" | sudo tee /etc/php/7.4/mods-available/ext_gmp.ini sudo ln -s /etc/php/7.4/mods-available/ext_gmp.ini /etc/php/7.4/cli/conf.d/20-ext_gmp.ini + +# Configure Horizon +php artisan queue:table +php artisan migrate +## Install Redis. Link: https://www.digitalocean.com/community/tutorials/how-to-install-and-secure-redis-on-ubuntu-20-04 +composer require predis/predis +composer require laravel/horizon +php artisan horizon:install +php artisan horizon:publish +## Configure Supervisor. Link: https://laravel.com/docs/9.x/horizon#installing-supervisor ( Only 'Installing Supervisor', 'Supervisor Configuration', 'Starting Supervisor' Sections ) ``` Setup the repo according to our VHOST path. Note, the actual VHOST path in this case should be set to **/var/www/CasperAssociationPortalBackend/public** diff --git a/ansible/roles/casper-association-portal-backend/defaults/main/main.yml b/ansible/roles/casper-association-portal-backend/defaults/main/main.yml index 70b31f0a..51304451 100644 --- a/ansible/roles/casper-association-portal-backend/defaults/main/main.yml +++ b/ansible/roles/casper-association-portal-backend/defaults/main/main.yml @@ -16,6 +16,8 @@ packages: - php7.4-curl - php7.4-xml - php7.4-gmp + - redis-server + - supervisor php: diff --git a/ansible/roles/casper-association-portal-backend/tasks/main.yml b/ansible/roles/casper-association-portal-backend/tasks/main.yml index d15a5cc6..4945cae7 100644 --- a/ansible/roles/casper-association-portal-backend/tasks/main.yml +++ b/ansible/roles/casper-association-portal-backend/tasks/main.yml @@ -232,7 +232,7 @@ cron: name: "{{ app.name }}" user: "{{ security.app_user }}" - job: "cd /var/www/server && php artisan schedule:run 2>&1" + job: "cd /var/www/server && sudo php artisan schedule:run 2>&1" minute: "*" hour: "*" day: "*" @@ -266,3 +266,13 @@ - config - first_setup when: clone_repo.changed + +- name: Horizon + shell: sudo supervisorctl reread && sudo supervisorctl update && sudo service supervisor restart + args: + chdir: "{{ app.home }}" + tags: + - php + - update + - horizon + when: clone_repo.changed diff --git a/ansible/roles/casper-association-portal-backend/templates/.env.j2 b/ansible/roles/casper-association-portal-backend/templates/.env.j2 index 2164dc7c..a60e1254 100644 --- a/ansible/roles/casper-association-portal-backend/templates/.env.j2 +++ b/ansible/roles/casper-association-portal-backend/templates/.env.j2 @@ -17,12 +17,13 @@ DB_PASSWORD={{ lookup('ansible.builtin.env', 'CA_MEMBER_PORT_BE_DB_PASSWORD') }} BROADCAST_DRIVER={{ broadcast.driver }} CACHE_DRIVER={{ cache.driver }} FILESYSTEM_DRIVER={{ filesystem.driver }} -QUEUE_CONNECTION={{ queue.connection }} +QUEUE_CONNECTION=redis SESSION_DRIVER={{ session.driver }} SESSION_LIFETIME={{ session.lifetime }} MEMCACHED_HOST={{ lookup('ansible.builtin.env', 'CA_MEMBER_PORT_BE_MEMCACHED_HOST') }} +REDIS_CLIENT=predis REDIS_HOST={{ lookup('ansible.builtin.env', 'CA_MEMBER_PORT_BE_REDIS_HOST') }} REDIS_PASSWORD={{ lookup('ansible.builtin.env', 'CA_MEMBER_PORT_BE_REDIS_PASSWORD') }} REDIS_PORT={{ lookup('ansible.builtin.env', 'CA_MEMBER_PORT_BE_REDIS_PORT') }} @@ -34,7 +35,7 @@ MAIL_USERNAME={{ lookup('ansible.builtin.env', 'CA_MEMBER_PORT_BE_MAIL_USERNAME' MAIL_PASSWORD={{ lookup('ansible.builtin.env', 'CA_MEMBER_PORT_BE_MAIL_PASSWORD') }} MAIL_ENCRYPTION={{ lookup('ansible.builtin.env', 'CA_MEMBER_PORT_BE_MAIL_ENCRYPTION') }} MAIL_FROM_ADDRESS={{ lookup('ansible.builtin.env', 'CA_MEMBER_PORT_BE_MAIL_FROM_ADDRESS') }} -MAIL_FROM_NAME="{{ lookup('ansible.builtin.env', 'CA_MEMBER_PORT_BE_MAIL_FROM_NAME') }}" +MAIL_FROM_NAME="{{ lookup('ansible.builtin.env', 'CA_MEMBER_PORT_BE_APP_NAME') }}" AWS_ACCESS_KEY_ID={{ lookup('ansible.builtin.env', 'CA_MEMBER_PORT_BE_AWS_KEY') }} AWS_SECRET_ACCESS_KEY={{ lookup('ansible.builtin.env', 'CA_MEMBER_PORT_BE_AWS_SECRET') }} diff --git a/app/Console/Commands/CheckBallot.php b/app/Console/Commands/CheckBallot.php index 639b1008..a1ed145d 100644 --- a/app/Console/Commands/CheckBallot.php +++ b/app/Console/Commands/CheckBallot.php @@ -2,6 +2,7 @@ namespace App\Console\Commands; +use App\Console\Helper; use App\Models\Ballot; use Carbon\Carbon; use Illuminate\Console\Command; @@ -39,10 +40,11 @@ public function __construct() */ public function handle() { - $settings = getSettings(); + $settings = Helper::getSettings(); $quorumRate = $settings['quorum_rate_ballot'] ?? 50; - $now = Carbon::now('UTC'); - $ballots = Ballot::with(['vote'])->where('status', 'active')->where('time_end', '<=', $now)->get(); + $ballots = Ballot::with(['vote'])->where('status', 'active') + ->where('time_end', '<=', Carbon::now('UTC')) + ->get(); foreach ($ballots as $ballot) { $vote = $ballot->vote; if ($vote->result_count == 0) { diff --git a/app/Console/Commands/CheckBallot2.php b/app/Console/Commands/CheckBallot2.php new file mode 100644 index 00000000..94d207e6 --- /dev/null +++ b/app/Console/Commands/CheckBallot2.php @@ -0,0 +1,37 @@ +where('status', 'active') + ->where('time_end', '<=', Carbon::now('UTC')->addHours(24)) + ->where('time_end', '>', Carbon::now('UTC')) + ->where('reminder_24_sent', false) + ->orderBy('time_end', 'asc') + ->get(); + + if ($ballots && count($ballots) > 0) { + foreach ($ballots as $ballot) { + BallotReminder24::dispatch($ballot)->onQueue('default_long'); + } + } + + return 0; + } +} \ No newline at end of file diff --git a/app/Console/Commands/CheckNodeStatus.php b/app/Console/Commands/CheckNodeStatus.php index 44a3e4a7..02ff95c5 100644 --- a/app/Console/Commands/CheckNodeStatus.php +++ b/app/Console/Commands/CheckNodeStatus.php @@ -2,275 +2,216 @@ namespace App\Console\Commands; +use App\Console\Helper; + use App\Models\MonitoringCriteria; use App\Models\User; use App\Models\UserAddress; use App\Models\NodeInfo; +use App\Models\AllNodeData2; +use App\Jobs\EmailerUserJob; use Carbon\Carbon; +use Illuminate\Support\Facades\DB; use Illuminate\Console\Command; use Illuminate\Support\Facades\Log; class CheckNodeStatus extends Command { - /** - * The name and signature of the console command. - * - * @var string - */ protected $signature = 'node-status:check'; - /** - * The console command description. - * - * @var string - */ protected $description = 'Check node status'; - /** - * Create a new command instance. - * - * @return void - */ - public function __construct() - { + public function __construct() { parent::__construct(); } - /** - * Execute the console command. - * - * @return int - */ - public function handle() - { - $uptime = MonitoringCriteria::where('type', 'uptime')->first(); - $uptimeProbationStart = $uptime->probation_start; - if ($uptime->given_to_correct_unit == 'Weeks') { - $uptimeTime = (float) $uptime->given_to_correct_value * 7 * 24; - } else if ($uptime->given_to_correct_unit == 'Days') { - $uptimeTime = (float) $uptime->given_to_correct_value * 24; - } else { - $uptimeTime = (float) $uptime->given_to_correct_value; - } + public function handle() { + $settings = Helper::getSettings(); - $blockHeight = MonitoringCriteria::where('type', 'block-height')->first(); - $blockHeightProbationStart = (float) $blockHeight->probation_start; - if ($blockHeight->given_to_correct_unit == 'Weeks') { - $blockHeightTime = (float) $blockHeight->given_to_correct_value * 7 * 24; - } else if ($blockHeight->given_to_correct_unit == 'Days') { - $blockHeightTime = (float) $blockHeight->given_to_correct_value * 24; - } else { - $blockHeightTime = (float) $blockHeight->given_to_correct_value; - } - - $updateResponsiveness = MonitoringCriteria::where('type', 'update-responsiveness')->first(); - $updateResponsivenessProbationStart = (float) $updateResponsiveness->probation_start; - if ($updateResponsiveness->given_to_correct_unit == 'Weeks') { - $updateResponsivenessTime = (float) $updateResponsiveness->given_to_correct_value * 7 * 24; - } else if ($updateResponsiveness->given_to_correct_unit == 'Days') { - $updateResponsivenessTime = (float) $updateResponsiveness->given_to_correct_value * 24; - } else { - $updateResponsivenessTime = (float) $updateResponsiveness->given_to_correct_value; - } + $current_era_id = (int) ($settings['current_era_id'] ?? 0); + $redmarks_revoke = (int) ($settings['redmarks_revoke'] ?? 0); + $uptime_probation = (float) ($settings['uptime_probation'] ?? 0); - $now = Carbon::now('UTC'); - $users = User::with(['addresses', 'metric', 'nodeInfo', 'profile']) + $users = User::with(['addresses', 'profile']) ->where('role', 'member') ->where('banned', 0) ->get(); - foreach ($users as $user) { - $user->node_status = 'Online'; - $user->save(); + $uptimeHours = 0; + if (isset($settings['uptime_correction_unit']) && isset($settings['uptime_correction_value'])) { + $unit = $settings['uptime_correction_unit']; + $value = (float) $settings['uptime_correction_value']; + + if ($unit == 'Weeks') $uptimeHours = $value * 7 * 24; + else if ($unit == 'Days') $uptimeHours = $value * 24; + else $uptimeHours = $value; + } + foreach ($users as $user) { $addresses = $user->addresses ?? []; - $nodeInfo = $user->nodeInfo ? $user->nodeInfo : $user->metric; if ( - !$nodeInfo || - !$addresses || - count($addresses) == 0 || - !$user->node_verified_at || - !$user->letter_verified_at || - !$user->signature_request_id + $addresses && + count($addresses) > 0 && + $user->node_verified_at && + $user->letter_verified_at && + $user->signature_request_id && + isset($user->profile) && + $user->profile && + $user->profile->status == 'approved' ) { - $user->node_status = null; - $user->save(); - } else { - $hasNotFailNode = false; - foreach ($addresses as $address) { - $public_address_node = strtolower($address->public_address_node); - $nodeInfoAddress = NodeInfo::where('node_address', $public_address_node)->first(); - if (!$nodeInfoAddress) { - $address->node_status = null; - $address->save(); - } - if ($address->is_fail_node != 1) { - $hasNotFailNode = true; + // Verified Users + if ($user->profile->extra_status == 'Suspended') { + // Suspended + if (!$user->profile->revoke_at) { + $user->profile->revoke_at = Carbon::now('UTC'); + $user->profile->save(); } - } - - if (!$hasNotFailNode) { - $user->node_status = 'Offline'; - $user->save(); } else { - // Begin For Each - foreach ($addresses as $userAddress) { - $public_address_node = strtolower($userAddress->public_address_node); - $nodeInfoAddress = NodeInfo::where('node_address', $public_address_node)->first(); - - if ($nodeInfoAddress) { - $nodeInfoAddress->uptime = $nodeInfoAddress->uptime ? $nodeInfoAddress->uptime : 0; - $nodeInfoAddress->block_height_average = $nodeInfoAddress->block_height_average ? $nodeInfoAddress->block_height_average : 0; - $nodeInfoAddress->update_responsiveness = $nodeInfoAddress->update_responsiveness ? $nodeInfoAddress->update_responsiveness : 100; - if ( - $nodeInfoAddress->uptime >= $uptimeProbationStart && - $nodeInfoAddress->block_height_average >= $blockHeightProbationStart && - $nodeInfoAddress->update_responsiveness >= $updateResponsivenessProbationStart - ) { - $userAddress->node_status = 'Online'; - $userAddress->save(); - - $nodeInfoAddress->uptime_time_start = null; - $nodeInfoAddress->uptime_time_end = null; - - $nodeInfoAddress->block_height_average_time_start = null; - $nodeInfoAddress->block_height_average_time_end = null; - - $nodeInfoAddress->update_responsiveness_time_start = null; - $nodeInfoAddress->update_responsiveness_time_end = null; - - $nodeInfoAddress->save(); - } - } - - if ( - isset($user->profile) && - $user->profile && - isset($user->profile->status) && - $user->profile->status == 'approved' && - $nodeInfoAddress - ) { - $userAddress->extra_status = null; - $userAddress->save(); - - if ($nodeInfoAddress->uptime < $uptimeProbationStart) { - $userAddress->extra_status = 'On Probation'; - - if(!$nodeInfoAddress->uptime_time_start) { - $nodeInfoAddress->uptime_time_start = now(); - } - - if(!$nodeInfoAddress->uptime_time_end) { - $nodeInfoAddress->uptime_time_end = Carbon::now('UTC')->addHours($uptimeTime); - } - } - - if ($nodeInfoAddress->block_height_average < $blockHeightProbationStart) { - $userAddress->extra_status = 'On Probation'; - - if(!$nodeInfoAddress->block_height_average_time_start) { - $nodeInfoAddress->block_height_average_time_start = now(); - } - - if(!$nodeInfoAddress->block_height_average_time_end) { - $nodeInfoAddress->block_height_average_time_end = Carbon::now('UTC')->addHours($blockHeightTime); + // Not Suspended + + $hasOnline = $hasOnProbation = $hasSuspended = false; + $revokeReason = []; + + foreach ($addresses as $address) { + $public_address_node = strtolower($address->public_address_node); + + $temp = AllNodeData2::select(['id', 'uptime']) + ->where('public_key', $public_address_node) + ->where('era_id', $current_era_id) + ->where('bid_inactive', 0) + ->where('in_auction', 1) + ->where('in_current_era', 1) + ->first(); + if ($temp) { + // All Node Data2 Record Exists! + + $hasOnline = true; + $address->node_status = 'Online'; + $address->extra_status = null; + $address->save(); + + // Check Redmarks + if ($redmarks_revoke > 0) { + $bad_marks = Helper::calculateBadMarksRevoke($temp, $public_address_node, $settings); + + if ($bad_marks > $redmarks_revoke) { + $address->extra_status = 'Suspended'; + $address->probation_start = null; + $address->probation_end = null; + $address->save(); + if (!in_array('Too many redmarks', $revokeReason)) { + $revokeReason[] = 'Too many redmarks'; + } } } - if ($nodeInfoAddress->update_responsiveness < $updateResponsivenessProbationStart) { - $userAddress->extra_status = 'On Probation'; - - if(!$nodeInfoAddress->update_responsiveness_time_start) { - $nodeInfoAddress->update_responsiveness_time_start = now(); - } - - if(!$nodeInfoAddress->update_responsiveness_time_end) { - $nodeInfoAddress->update_responsiveness_time_end = Carbon::now('UTC')->addHours($updateResponsivenessTime); + // Check Historical Performance + if (!$address->extra_status && $uptime_probation > 0) { + $uptime = Helper::calculateUptime($temp, $public_address_node, $settings); + + if ($uptime < $uptime_probation) { + $address->extra_status = 'On Probation'; + if (!$address->probation_start || !$address->probation_end) { + $address->probation_start = Carbon::now('UTC'); + $address->probation_end = Carbon::now('UTC')->addHours($uptimeHours); + } + $address->save(); + + if ($address->probation_end <= Carbon::now('UTC')) { + $address->extra_status = 'Suspended'; + $address->probation_start = null; + $address->probation_end = null; + $address->save(); + if (!in_array('Poor uptime', $revokeReason)) { + $revokeReason[] = 'Poor uptime'; + } + } else { + $hasOnProbation = true; + } + } else { + $address->probation_start = null; + $address->probation_end = null; + $address->save(); } } - $userAddress->save(); - $nodeInfoAddress->save(); - - if ($userAddress->extra_status == 'On Probation') { - if ($nodeInfoAddress->uptime_time_end <= $now && $nodeInfoAddress->uptime < $uptimeProbationStart) { - $userAddress->extra_status = 'Suspended'; - } - if ($nodeInfoAddress->block_height_average_time_end <= $now && $nodeInfoAddress->block_height_average < $blockHeightProbationStart) { - $userAddress->extra_status = 'Suspended'; - } - if ($nodeInfoAddress->update_responsiveness_time_end <= $now && $nodeInfoAddress->update_responsiveness < $updateResponsivenessProbationStart) { - $userAddress->extra_status = 'Suspended'; - } - $userAddress->save(); + if ($address->extra_status == 'Suspended') { + $hasSuspended = true; } - } - - $inactive = (bool)($nodeInfoAddress->inactive ?? false); - - if($inactive) { - $userAddress->node_status = 'Offline'; - $userAddress->extra_status = 'Suspended'; - $userAddress->save(); - } - } - // End For Each - - // Begin For Each - $hasNotOfflineStatus = $hasNotSuspendedStatus = false; - foreach ($addresses as $userAddress) { - if ($userAddress->node_status != 'Offline') { - $hasNotOfflineStatus = true; - break; - } - } - foreach ($addresses as $userAddress) { - if ($userAddress->extra_status != 'Suspended') { - $hasNotSuspendedStatus = true; - break; + } else { + // All Node Data2 Record Doesn't Exist! + + $address->node_status = 'Offline'; + $address->extra_status = null; + $address->probation_start = null; + $address->probation_end = null; + $address->save(); } } - if (!$hasNotOfflineStatus) { + if ($hasOnline) { + $user->node_status = 'Online'; + $user->save(); + } else { $user->node_status = 'Offline'; $user->save(); + } + + if ($hasOnProbation) { + $orgStatus = $user->profile->extra_status; + + $user->profile->extra_status = 'On Probation'; + $user->profile->save(); + + if ($orgStatus && $orgStatus == 'On Probation') { + // + } else { + EmailerUserJob::dispatch($user, 'User goes on probation'); + } } else { - foreach ($addresses as $userAddress) { - if ($userAddress->node_status == 'Online') { - $user->node_status = 'Online'; - $user->save(); - break; - } - } - if ($user->node_status != 'Online') { - $user->node_status = null; - $user->save(); - } + $user->profile->extra_status = null; + $user->profile->save(); } - if ( - !$hasNotSuspendedStatus && - isset($user->profile) && - $user->profile - ) { + if ($hasOnline && $hasSuspended) { + $orgStatus = $user->profile->extra_status; + $user->profile->extra_status = 'Suspended'; - $user->profile->save(); - } else if (isset($user->profile) && $user->profile) { - foreach ($addresses as $userAddress) { - if ($userAddress->extra_status == 'On Probation') { - $user->profile->extra_status = 'On Probation'; - $user->save(); - break; - } - } - if ($user->profile->extra_status != 'On Probation') { - $user->profile->extra_status = null; - $user->profile->save(); + $user->profile->revoke_at = Carbon::now('UTC'); + if (count($revokeReason) > 0) { + $user->profile->revoke_reason = implode(', ', $revokeReason); } + $user->profile->save(); + + if ($orgStatus && $orgStatus == 'Suspended') { + // + } else { + EmailerUserJob::dispatch($user, 'User membership is revoked'); + } + } + } + } else { + // Non-Verified Users + + $user->node_status = null; + $user->save(); + + if ($user->profile) { + $user->profile->extra_status = null; + $user->profile->revoke_reason = null; + $user->profile->save(); + } + + if ($addresses && count($addresses) > 0) { + foreach ($addresses as $address) { + $address->node_status = null; + $address->extra_status = null; + $address->probation_start = null; + $address->probation_end = null; + $address->save(); } - // End For Each } } } diff --git a/app/Console/Commands/CheckUpgrade.php b/app/Console/Commands/CheckUpgrade.php new file mode 100644 index 00000000..35ca4931 --- /dev/null +++ b/app/Console/Commands/CheckUpgrade.php @@ -0,0 +1,30 @@ +limit(1)->first(); + if ( + !$lastUpgrade->reminder_24_sent && + $lastUpgrade->activation_datetime > Carbon::now('UTC') && + $lastUpgrade->activation_datetime <= Carbon::now('UTC')->addHours(24) + ) { + UpgradeReminder24::dispatch($lastUpgrade)->onQueue('default_long'); + } + return 0; + } +} diff --git a/app/Console/Commands/HistoricalData.php b/app/Console/Commands/HistoricalData.php new file mode 100644 index 00000000..e1d88d32 --- /dev/null +++ b/app/Console/Commands/HistoricalData.php @@ -0,0 +1,386 @@ +result->block->header->era_id ?? 0); + + $historic_era = DB::select(" + SELECT era_id + FROM all_node_data2 + ORDER BY era_id DESC + LIMIT 1 + "); + + $historic_era = (int)($historic_era[0]->era_id ?? 6000); + $historic_block = 1; + $test_era = 0; + $timestamp = '1'; + + // reductive binary search algorithm + // $m = 1073741824; + $m = 1; + + // find max in range first + while ($timestamp != '') { + $m *= 2; + $json = shell_exec($get_block.$node_arg.'-b '.$m); + $json = json_decode($json); + $test_era = (int)($json->result->block->header->era_id ?? 0); + info('finding max block ... '.$m); + $timestamp = $json->result->block->header->timestamp ?? ''; + } + + // run search algo + $historic_block = $m; + + while ($test_era != $historic_era) { + $json = shell_exec($get_block.$node_arg.'-b '.$historic_block); + $json = json_decode($json); + $test_era = (int)($json->result->block->header->era_id ?? 0); + info('trying historic_block '.$historic_block.' ... got era: '.$test_era); + $timestamp = $json->result->block->header->timestamp ?? ''; + + if ( + !$timestamp || $timestamp == '' || + $test_era > $historic_era + ) { + info('historic_block too high'); + $historic_block -= $m; + if ($historic_block < 1) $historic_block = 1; + $m = (int)($m / 2); + continue; + } + + if ($test_era < $historic_era) { + info('historic_block too low'); + $historic_block += $m; + $m = (int)($m / 2); + continue; + } + } + + while ($current_era >= $historic_era) { + // first see if we have this era's auction info + $node_data = DB::select(" + SELECT era_id + FROM all_node_data2 + WHERE era_id = $historic_era + "); + $node_data = (int) ($node_data[0]->era_id ?? 0); + + if ($node_data > 0) { + // era's auction info exists. do not need to fetch. + info('Already have era ' . $historic_era . ' data. skipping'); + $historic_era += 1; + } else { + // decrease block height and check for new switch block + $command = $get_block . $node_arg . '-b ' . $historic_block; + $switch_block = shell_exec($command); + $json = json_decode($switch_block); + $era_id = (int)($json->result->block->header->era_id ?? 0); + info('Checking block '.$historic_block.' for era '.$historic_era.'. Found era '.$era_id); + $block_hash = $json->result->block->hash ?? ''; + $timestamp = $json->result->block->header->timestamp ?? ''; + $timestamp = Carbon::parse($timestamp)->format('Y-m-d H:i:s'); + + if ($era_id == 0) { + break; + } + + if ($era_id == $historic_era) { + // start timer + $start_time = (int) time(); + + // get auction info for this new detected era switch + info($era_id . ' ' . $block_hash); + $historic_era += 1; + $command = $get_auction . $node_arg . '-b ' . $block_hash; + $auction_info = shell_exec($command); + + // very large object. aprx 10MB + $decoded_response = json_decode($auction_info); + $auction_state = $decoded_response->result->auction_state ?? []; + $bids = $auction_state->bids ?? []; + + // get era ID + $era_validators = $auction_state->era_validators ?? []; + $current_era_validators = $era_validators[0] ?? []; + $next_era_validators = $era_validators[1] ?? []; + $current_era_id = (int)($current_era_validators->era_id ?? 0); + $next_era_id = (int)($next_era_validators->era_id ?? 0); + + info('Data aquired for era: ' . $current_era_id); + + // set MBS array. minimum bid slot amount + $MBS_arr = []; + + // get global uptimes from MAKE + $global_uptime = $nodeHelper->retrieveGlobalUptime($current_era_id); + + // Set validator key object + $data = [ + 'era_id' => $era_id, + 'validators' => [] + ]; + + // loop auction era + info('Looping auction era - Appending uptime, bid, and daily earnings data'); + foreach ($bids as $b) { + $public_key = strtolower($b->public_key ?? 'nill'); + $bid = $b->bid ?? []; + + // get self + $self_staked_amount = (int) ($bid->staked_amount ?? 0); + $delegation_rate = (int) ($bid->delegation_rate ?? 0); + $bid_inactive = (int) ($bid->inactive ?? false); + + // calculate total stake, delegators + self stake + $delegators = (array) ($bid->delegators ?? []); + $delegators_count = count($delegators); + $delegators_staked_amount = 0; + + foreach ($delegators as $delegator) { + $delegators_staked_amount += (int) ($delegator->staked_amount ?? 0); + } + + // convert and calculate stake amounts + $delegators_staked_amount = (int) ($delegators_staked_amount / 1000000000); + $self_staked_amount = (int) ($self_staked_amount / 1000000000); + $total_staked_amount = $delegators_staked_amount + $self_staked_amount; + + // append to MBS array and pluck 100th place later + $MBS_arr[$public_key] = $total_staked_amount; + + // get node uptime from MAKE object + $uptime = 0; + + foreach ($global_uptime as $uptime_array) { + $fvid = strtolower($uptime_array->public_key ?? ''); + if ($fvid == $public_key) { + $uptime = (float)($uptime_array->average_score ?? 0); + break; + } + } + + // define DB insert object for all public keys in this era + $data['validators'][$public_key] = [ + 'public_key' => $public_key, + 'uptime' => $uptime, + 'current_era_weight' => 0, + 'next_era_weight' => 0, + 'in_current_era' => 0, + 'in_next_era' => 0, + 'in_auction' => 1, + 'bid_delegators_count' => $delegators_count, + 'bid_delegation_rate' => $delegation_rate, + 'bid_inactive' => $bid_inactive, + 'bid_self_staked_amount' => $self_staked_amount, + 'bid_delegators_staked_amount' => $delegators_staked_amount, + 'bid_total_staked_amount' => $total_staked_amount, + 'port8888_peers' => 0, + 'port8888_build_version' => '', + 'port8888_next_upgrade' => '' + ]; + + // look for existing peer by public key for port 8888 data + foreach ($port8888_responses as $port8888data) { + $our_public_signing_key = strtolower($port8888data['our_public_signing_key'] ?? ''); + + if ($our_public_signing_key == $public_key) { + // found in peers + $peer_count = (int) ($port8888data['peer_count'] ?? 0); + $era_id = (int) ($port8888data['last_added_block_info']['era_id'] ?? 0); + $block_height = (int) ($port8888data['last_added_block_info']['height'] ?? 0); + $build_version = $port8888data['build_version'] ?? '1.0.0'; + $build_version = explode('-', $build_version)[0]; + $chainspec_name = $port8888data['chainspec_name'] ?? 'casper'; + $next_upgrade = $port8888data['next_upgrade']['protocol_version'] ?? ''; + break; + } + } + } + + // loop current era + $current_validator_weights = $current_era_validators->validator_weights ?? []; + info('Appending current era validator weights'); + + foreach ($current_validator_weights as $v) { + $public_key = strtolower($v->public_key ?? ''); + $weight = (int) ($v->weight / 1000000000 ?? 0); + + if (isset($data["validators"][$public_key])) { + $data['validators'][$public_key]['current_era_weight'] = $weight; + $data['validators'][$public_key]['in_current_era'] = 1; + } else { + $data['validators'][$public_key] = [ + 'public_key' => $public_key, + 'uptime' => 0, + 'current_era_weight' => $weight, + 'next_era_weight' => 0, + 'in_current_era' => 1, + 'in_next_era' => 0, + 'in_auction' => 0, + 'bid_delegators_count' => 0, + 'bid_delegation_rate' => 0, + 'bid_inactive' => 1, + 'bid_self_staked_amount' => 0, + 'bid_delegators_staked_amount' => 0, + 'bid_total_staked_amount' => 0, + 'port8888_peers' => 0, + 'port8888_build_version' => '', + 'port8888_next_upgrade' => '' + ]; + } + } + + // loop next era + $next_validator_weights = $next_era_validators->validator_weights ?? []; + info('Appending next era validator weights'); + + foreach ($next_validator_weights as $v) { + $public_key = $v->public_key ?? ''; + $weight = (int) ($v->weight / 1000000000 ?? 0); + + if (isset($data["validators"][$public_key])) { + $data['validators'][$public_key]['next_era_weight'] = $weight; + $data['validators'][$public_key]['in_next_era'] = 1; + } else { + $data['validators'][$public_key] = [ + 'public_key' => $public_key, + 'uptime' => 0, + 'current_era_weight' => $weight, + 'next_era_weight' => 0, + 'in_current_era' => 1, + 'in_next_era' => 0, + 'in_auction' => 0, + 'bid_delegators_count' => 0, + 'bid_delegation_rate' => 0, + 'bid_inactive' => 1, + 'bid_self_staked_amount' => 0, + 'bid_delegators_staked_amount' => 0, + 'bid_total_staked_amount' => 0, + 'port8888_peers' => 0, + 'port8888_build_version' => '', + 'port8888_next_upgrade' => '' + ]; + } + } + + // Primary DB insertion (time consuming) + info('Saving validator objects to DB...'); + + foreach ($data["validators"] as $v) { + DB::table('all_node_data2')->insert( + [ + 'public_key' => $v['public_key'], + 'era_id' => $data['era_id'], + 'uptime' => $v['uptime'], + 'current_era_weight' => $v['current_era_weight'], + 'next_era_weight' => $v['next_era_weight'], + 'in_current_era' => $v['in_current_era'], + 'in_next_era' => $v['in_next_era'], + 'in_auction' => $v['in_auction'], + 'bid_delegators_count' => $v['bid_delegators_count'], + 'bid_delegation_rate' => $v['bid_delegation_rate'], + 'bid_inactive' => $v['bid_inactive'], + 'bid_self_staked_amount' => $v['bid_self_staked_amount'], + 'bid_delegators_staked_amount' => $v['bid_delegators_staked_amount'], + 'bid_total_staked_amount' => $v['bid_total_staked_amount'], + 'port8888_peers' => $v['port8888_peers'], + 'port8888_build_version' => $v['port8888_build_version'], + 'port8888_next_upgrade' => $v['port8888_next_upgrade'], + 'created_at' => $timestamp + ] + ); + + info($v["public_key"] . ' - done'); + } + + // find MBS + info('Finding MBS for this era'); + rsort($MBS_arr); + $MBS = 0; + if (count($MBS_arr) > 0) { + $MBS = (float) ($MBS_arr[99] ?? $MBS_arr[count($MBS_arr) - 1]); + } + + // save MBS in new table by current_era + $check = DB::select(" + SELECT mbs + FROM mbs + WHERE era_id = $current_era_id + "); + $check = $check[0] ?? null; + + if (!$check) { + DB::table('mbs')->insert([ + 'era_id' => $current_era_id, + 'mbs' => $MBS, + 'created_at' => $timestamp + ]); + } else { + DB::table('mbs') + ->where('era_id', $current_era_id) + ->update([ + 'mbs' => $MBS, + 'updated_at' => $timestamp + ]); + } + + // end timer + $end_time = (int) time(); + + info("Time spent on era: " . ($end_time - $start_time)); + } + $historic_block += 5; + } + } + info('done'); + } +} \ No newline at end of file diff --git a/app/Console/Commands/KycReport.php b/app/Console/Commands/KycReport.php index fca59009..3b17b0ae 100644 --- a/app/Console/Commands/KycReport.php +++ b/app/Console/Commands/KycReport.php @@ -45,26 +45,26 @@ public function __construct() public function handle() { // first do shufti temp records - $now = Carbon::now(); - $yesterday = Carbon::now()->subHours(12); + $now = Carbon::now('UTC'); + $yesterday = Carbon::now('UTC')->subHours(12); $records_temp = ShuftiproTemp::where('status', 'pending') ->where('created_at', '<=', $yesterday) ->limit(10) ->get(); - $persons_stuck_in_pending = array(); - $known_reference_ids = array(); + $persons_stuck_in_pending = []; + $known_reference_ids = []; if($records_temp) { foreach($records_temp as $record) { $user_id = $record->user_id ?? 0; $person = User::where('id', $user_id)->first(); - $persons_stuck_in_pending[] = array( - "name" => $person->first_name.' '.$person->last_name, - "email" => $person->email, - "shufti_reference_id" => $record->reference_id, - "shufti_timestamp" => $record->created_at - ); + $persons_stuck_in_pending[] = [ + 'name' => $person->first_name.' '.$person->last_name, + 'email' => $person->email, + 'shufti_reference_id' => $record->reference_id, + 'shufti_timestamp' => $record->created_at + ]; $known_reference_ids[] = $record->reference_id; } @@ -76,33 +76,33 @@ public function handle() ->limit(10) ->get(); - $persons_stuck_denied = array(); + $persons_stuck_denied = []; if($records_pro) { foreach($records_pro as $record) { if(!in_array($record->reference_id, $known_reference_ids)) { $user_id = $record->user_id ?? 0; $person = User::where('id', $user_id)->first(); - $persons_stuck_denied[] = array( - "name" => $person->first_name.' '.$person->last_name, - "email" => $person->email, - "shufti_reference_id" => $record->reference_id, - "shufti_timestamp" => $record->created_at - ); + $persons_stuck_denied[] = [ + 'name' => $person->first_name.' '.$person->last_name, + 'email' => $person->email, + 'shufti_reference_id' => $record->reference_id, + 'shufti_timestamp' => $record->created_at + ]; } } } // now make a text list from the matching records - $body = ""; + $body = ''; $index = 1; if($persons_stuck_in_pending) { $body .= "Members pending for over 24 hours:
"; foreach($persons_stuck_in_pending as $p) { - $body .= ''.(string)$index.'. '; - $body .= $p['name'].', '.$p['email'].'
'; + $body .= '' . (string) $index . '. '; + $body .= $p['name'] . ', ' . $p['email'] . '
'; $index += 1; } } @@ -117,8 +117,8 @@ public function handle() $body .= "Members denied by Shufti. Not reviewed yet:
"; foreach($persons_stuck_denied as $p) { - $body .= ''.(string)$index.'. '; - $body .= $p['name'].', '.$p['email'].'
'; + $body .= '' . (string)$index . '. '; + $body .= $p['name'] . ', ' . $p['email'] . '
'; $index += 1; } } @@ -126,7 +126,7 @@ public function handle() // compose email to admins if($persons_stuck_in_pending || $persons_stuck_denied) { $emailerData = EmailerHelper::getEmailerData(); - $admins = $emailerData['admins'] ?? array(); + $admins = $emailerData['admins'] ?? []; if($admins) { Mail::to($admins)->send(new AdminAlert('Casper Association portal KYC issues require attention', $body)); diff --git a/app/Console/Commands/MoveAddresses.php b/app/Console/Commands/MoveAddresses.php deleted file mode 100644 index 934cf0d4..00000000 --- a/app/Console/Commands/MoveAddresses.php +++ /dev/null @@ -1,73 +0,0 @@ -whereNotNull('public_address_node')->get(); - if ($users && count($users) > 0) { - foreach ($users as $user) { - $address = $user->public_address_node; - $userAddress = UserAddress::where('public_address_node', $address)->first(); - if (!$userAddress) { - $userAddress = new UserAddress; - $userAddress->user_id = $user->id; - $userAddress->public_address_node = $address; - $userAddress->node_verified_at = $user->node_verified_at; - $userAddress->signed_file = $user->signed_file; - $userAddress->is_fail_node = $user->is_fail_node; - $userAddress->rank = $user->rank; - $userAddress->pending_node = $user->pending_node; - $userAddress->validator_fee = $user->validator_fee; - $userAddress->node_status = $user->node_status; - if ($user->profile && $user->profile->extra_status) { - $userAddress->extra_status = $user->profile->extra_status; - } - $userAddress->save(); - } - $user->has_address = 1; - if ($user->node_verified_at) { - $user->has_verified_address = 1; - } - $user->save(); - } - } - return 0; - } -} diff --git a/app/Console/Commands/NodeInfo.php b/app/Console/Commands/NodeInfo.php deleted file mode 100644 index 1801a076..00000000 --- a/app/Console/Commands/NodeInfo.php +++ /dev/null @@ -1,226 +0,0 @@ -updateStats(); - $this->updateNode(); - // $this->updateUptime(); - $this->updateRank(); - } - - public function updateNode() - { - $nodes = Node::whereNotNull('protocol_version')->get(); - $max_hight_block = $nodes->max('block_height'); - $base_block = 10; - $versions = $nodes->pluck('protocol_version'); - $versions = $versions->toArray(); - usort($versions, 'version_compare'); - $highestVersion = (end($versions)); - $grouped = $nodes->groupBy('node_address'); - foreach ($grouped as $key => $values) { - $key = strtolower($key); - - $versionsNodes = $values->pluck('protocol_version'); - $versionsNodes = $versionsNodes->toArray(); - - usort($versionsNodes, 'version_compare'); - - $highestVersionNode = (end($versionsNodes)); - if (version_compare($highestVersion, $highestVersionNode, '<')) { - $userAddress = UserAddress::where('public_address_node', $key)->first(); - if ($userAddress) { - $userAddress->is_fail_node = 1; - $userAddress->node_status = 'Offline'; - $userAddress->save(); - } - } - - $totalResponsiveness = $totalBlockHeight = 0; - - $nodeInfo = ModelsNodeInfo::where('node_address', $key)->first(); - if ($nodeInfo) { - $groupedVersion = $values->groupBy('protocol_version'); - $countVersion = count($groupedVersion); - $totalArray = []; - - foreach ($groupedVersion as $ver => $items) { - $countItem = count($items); - $totalVerResponsiveness = 0; - $totalVerBlockHeight = 0; - $totalVerPeer = 0; - - foreach ($items as $item) { - $totalVerResponsiveness += $item->update_responsiveness; - $totalVerBlockHeight += $item->block_height; - $totalVerPeer += $item->peers; - } - - $totalArray[$ver] = [ - 'totalVerResponsiveness' => round($totalVerResponsiveness / $countItem), - 'totalVerBlockHeight' => round($totalVerBlockHeight / $countItem), - 'totalVerPeer' => round($totalVerPeer / $countItem), - ]; - } - foreach ($totalArray as $total) { - $totalResponsiveness += $total['totalVerResponsiveness']; - $totalBlockHeight += $total['totalVerBlockHeight']; - } - $block_height = round($totalBlockHeight / $countVersion); - $block_height_average = ($base_block - ($max_hight_block - $block_height)) * 10; - if ($block_height_average <= 0) { - $block_height_average = 0; - } - $nodeInfo->block_height_average = $block_height_average; - $nodeInfo->save(); - } - } - - $users = User::with(['addresses']) - ->where('role', 'member') - ->where('banned', 0) - ->get(); - if ($users && count($users) > 0) { - foreach ($users as $user) { - $addresses = $user->addresses ?? null; - if (!$addresses) { - $user->is_fail_node = 1; - $user->node_status = 'Offline'; - $user->save(); - } else if (count($addresses) > 0) { - $hasNotFailNode = $hasNotOfflineStatus = false; - foreach ($addresses as $address) { - if ($address->is_fail_node != 1) { - $hasNotFailNode = true; - } - if ($address->node_status != 'Offline') { - $hasNotOfflineStatus = true; - } - } - if (!$hasNotFailNode) { - $user->is_fail_node = 1; - $user->node_status = 'Offline'; - $user->save(); - } else if (!$hasNotOfflineStatus) { - $user->node_status = 'Offline'; - $user->save(); - } - } - } - } - } - - public function updateUptime() - { - $nodes = ModelsNodeInfo::get(); - $now = Carbon::now('UTC'); - $time = $now->subDays(14); - foreach ($nodes as $node) { - $avg_uptime = Node::where('node_address', strtolower($node->node_address)) - ->whereNotNull('uptime') - ->where('created_at', '>=', $time) - ->avg('uptime'); - $node->uptime = $avg_uptime * 100; - $node->save(); - } - } - - public function updateRank() - { - $slide_value_uptime = $slide_value_update_responsiveness = $slide_value_delegotors = $slide_value_stake_amount = $slide_delegation_rate = 20; - - $max_uptime = Node::max('uptime'); - $max_uptime = $max_uptime * 100; - $max_delegators = ModelsNodeInfo::max('delegators_count'); - $max_stake_amount = ModelsNodeInfo::max('total_staked_amount'); - - DB::table('user_addresses')->update(['rank' => null]); - $userAddresses = UserAddress::with(['user', 'user.metric', 'user.nodeInfo']) - ->leftJoin('node_info', 'user_addresses.public_address_node', '=', 'node_info.node_address') - ->select([ - 'user_addresses.*', - 'node_info.delegation_rate', - 'node_info.delegators_count', - 'node_info.total_staked_amount', - ]) - ->whereHas('user') - ->get(); - - foreach ($userAddresses as $userAddress) { - $latest = Node::where('node_address', strtolower($userAddress->public_address_node))->whereNotnull('protocol_version')->orderBy('created_at', 'desc')->first(); - if (!$latest) $latest = new Node(); - $delegation_rate = $userAddress->delegation_rate ? $userAddress->delegation_rate / 100 : 1; - if (!$userAddress->user->metric && !$userAddress->user->nodeInfo) { - $userAddress->totalScore = null; - continue; - } - $latest_uptime_node = isset($latest->uptime) ? $latest->uptime * 100 : null; - $latest_update_responsiveness_node = $latest->update_responsiveness ?? null; - $metric = $userAddress->user->metric; - if (!$metric) $metric = new Metric(); - - $latest_uptime_metric = $metric->uptime ? $metric->uptime : null; - $latest_update_responsiveness_metric = $metric->update_responsiveness ? $metric->update_responsiveness : null; - - $latest_uptime = $latest_uptime_node ?? $latest_uptime_metric ?? 1; - $latest_update_responsiveness = $latest_update_responsiveness_node ?? $latest_update_responsiveness_metric ?? 1; - - $delegators_count = $userAddress->delegators_count ? $userAddress->user->nodeInfo->delegators_count : 0; - $total_staked_amount = $userAddress->total_staked_amount ? $userAddress->user->nodeInfo->total_staked_amount : 0; - - $uptime_score = ($slide_value_uptime * $latest_uptime) / 100; - $update_responsiveness_score = ($slide_value_update_responsiveness * $latest_update_responsiveness) / 100; - $dellegator_score = ($delegators_count / $max_delegators) * $slide_value_delegotors; - $stake_amount_score = ($total_staked_amount / $max_stake_amount) * $slide_value_stake_amount; - $delegation_rate_score = ($slide_delegation_rate * (1 - $delegation_rate)) / 100; - $totalScore = $uptime_score + $update_responsiveness_score + $dellegator_score + $stake_amount_score + $delegation_rate_score; - - $userAddress->totalScore = $totalScore; - } - $userAddresses = $userAddresses->sortByDesc('totalScore')->values(); - foreach ($userAddresses as $key => $userAddress) { - UserAddress::where('id', $userAddress->id)->update(['rank' => $key + 1]); - $user = User::where('public_address_node', $userAddress->public_address_node)->first(); - if ($user) { - $user->rank = $key + 1; - $user->save(); - } - } - } -} \ No newline at end of file diff --git a/app/Console/Commands/NotifCheck.php b/app/Console/Commands/NotifCheck.php index 4fe87980..f1eb5062 100644 --- a/app/Console/Commands/NotifCheck.php +++ b/app/Console/Commands/NotifCheck.php @@ -39,9 +39,13 @@ public function __construct() */ public function handle() { - $now = Carbon::now()->format('Y-m-d'); + $now = Carbon::now('UTC')->format('Y-m-d'); // check notification waiting - $waitingNotification = Notification::where('status', 'waiting')->where('setting', 1)->where('start_date', '<=', $now)->where('end_date', '>=', $now)->get(); + $waitingNotification = Notification::where('status', 'waiting') + ->where('setting', 1) + ->where('start_date', '<=', $now) + ->where('end_date', '>=', $now) + ->get(); foreach ($waitingNotification as $data) { $data->status = 'active'; $data->visibility = 'visible'; @@ -49,7 +53,9 @@ public function handle() } // check notification expired - $expiredNotification = Notification::where('end_date', '<', $now)->where('setting', 1)->get(); + $expiredNotification = Notification::where('end_date', '<', $now) + ->where('setting', 1) + ->get(); foreach ($expiredNotification as $data) { $data->status = 'expired'; $data->visibility = 'hidden'; diff --git a/app/Console/Commands/PerkCheck.php b/app/Console/Commands/PerkCheck.php index 6d4a47eb..62571af5 100644 --- a/app/Console/Commands/PerkCheck.php +++ b/app/Console/Commands/PerkCheck.php @@ -3,6 +3,7 @@ namespace App\Console\Commands; use App\Models\Perk; +use App\Jobs\PerkNotification; use Carbon\Carbon; use Illuminate\Console\Command; @@ -39,17 +40,27 @@ public function __construct() */ public function handle() { - $now = Carbon::now()->format('Y-m-d'); + $now = Carbon::now('UTC'); + // check perk waiting - $waitingPerks = Perk::where('status', 'waiting')->where('setting', 1)->where('start_date', '<=', $now)->where('end_date', '>=', $now)->get(); + $waitingPerks = Perk::where('status', 'waiting') + ->where('setting', 1) + ->where('time_begin', '<=', $now) + ->where('time_end', '>=', $now) + ->get(); foreach ($waitingPerks as $perk) { $perk->status = 'active'; $perk->visibility = 'visible'; $perk->save(); - } + PerkNotification::dispatch($perk)->onQueue('default_long'); + } + // check perk expired - $expiredPerks = Perk::where('end_date', '<', $now)->where('setting', 1)->where('status', '!=', 'expired')->get(); + $expiredPerks = Perk::where('time_end', '<', $now) + ->where('setting', 1) + ->where('status', '!=', 'expired') + ->get(); foreach ($expiredPerks as $perk) { $perk->status = 'expired'; $perk->visibility = 'hidden'; diff --git a/app/Console/Commands/RefreshAddress.php b/app/Console/Commands/RefreshAddress.php deleted file mode 100644 index 54b32cc5..00000000 --- a/app/Console/Commands/RefreshAddress.php +++ /dev/null @@ -1,98 +0,0 @@ -where('refreshed', 0) - ->orderBy('created_at', 'asc') - ->offset(0) - ->limit(50) - ->get(); - if ($nodes) { - foreach ($nodes as $node) { - $address = strtolower($node->node_address); - // $newAddress = (new ChecksumValidator())->do($address); - $node->node_address = $address; - $node->refreshed = 1; - $node->save(); - } - } - - $nodeInfos = NodeInfo::whereNotNull('node_address') - ->where('refreshed', 0) - ->orderBy('created_at', 'asc') - ->offset(0) - ->limit(50) - ->get(); - - if ($nodeInfos) { - foreach ($nodeInfos as $nodeInfo) { - $address = strtolower($nodeInfo->node_address); - // $newAddress = (new ChecksumValidator())->do($address); - $nodeInfo->node_address = $address; - $nodeInfo->refreshed = 1; - $nodeInfo->save(); - } - } - - $users = User::whereNotNull('public_address_node') - ->where('refreshed', 0) - ->orderBy('created_at', 'asc') - ->offset(0) - ->limit(50) - ->get(); - if ($users) { - foreach ($users as $user) { - $address = strtolower($user->public_address_node); - // $newAddress = (new ChecksumValidator())->do($address); - $user->public_address_node = $address; - $user->refreshed = 1; - $user->save(); - } - } - - return 0; - } -} diff --git a/app/Console/Commands/ShuftiproCheck.php b/app/Console/Commands/ShuftiproCheck.php deleted file mode 100644 index 45f93e24..00000000 --- a/app/Console/Commands/ShuftiproCheck.php +++ /dev/null @@ -1,58 +0,0 @@ -orderBy('id', 'asc') - ->get(); - - foreach ($records as $record) { - try { - $shuftiproCheck->handle($record); - } catch (\Exception $th) { - Log::error($th->getMessage()); - } - } - } -} diff --git a/app/Console/Helper.php b/app/Console/Helper.php index 7145edd2..1b7235fd 100644 --- a/app/Console/Helper.php +++ b/app/Console/Helper.php @@ -9,6 +9,8 @@ use App\Models\Profile; use App\Models\Shuftipro; use App\Models\User; +use App\Models\Setting; +use App\Models\AllNodeData2; use Illuminate\Support\Facades\DB; use Illuminate\Support\Facades\Http; @@ -22,6 +24,291 @@ class Helper { + public static function generateString($strength = 16) { + $seed = str_split('ABCDEFGHJKLMNPQRSTUVWXYZ' . '2345678923456789'); + + shuffle($seed); + $hash = ''; + + foreach(array_rand($seed, $strength) as $k) { + $hash .= $seed[$k]; + } + + return $hash; + } + + public static function checkAddressValidity($public_address_node) { + $current_era_id = self::getCurrentERAId(); + + $temp = AllNodeData2::select(['id']) + ->where('public_key', $public_address_node) + ->where('era_id', $current_era_id) + ->first(); + if ($temp) return true; + return false; + } + + public static function getSettings() { + $items = Setting::get(); + $settings = []; + if ($items) { + foreach ($items as $item) { + $settings[$item->name] = $item->value; + } + } + if (!isset($settings['peers'])) $settings['peers'] = 0; + if (!isset($settings['eras_look_back'])) $settings['eras_look_back'] = 1; + if (!isset($settings['eras_to_be_stable'])) $settings['eras_to_be_stable'] = 1; + if (!isset($settings['voting_eras_to_vote'])) $settings['voting_eras_to_vote'] = 1; + if (!isset($settings['uptime_calc_size'])) $settings['uptime_calc_size'] = 1; + if (!isset($settings['voting_eras_since_redmark'])) $settings['voting_eras_since_redmark'] = 1; + if (!isset($settings['uptime_warning'])) $settings['uptime_warning'] = 1; + if (!isset($settings['uptime_probation'])) $settings['uptime_probation'] = 1; + if (!isset($settings['uptime_correction_unit'])) $settings['uptime_correction_unit'] = 'Weeks'; + if (!isset($settings['uptime_correction_value'])) $settings['uptime_correction_value'] = 1; + if (!isset($settings['redmarks_revoke'])) $settings['redmarks_revoke'] = 1; + if (!isset($settings['redmarks_revoke_calc_size'])) $settings['redmarks_revoke_calc_size'] = 1; + if (!isset($settings['responsiveness_warning'])) $settings['responsiveness_warning'] = 1; + if (!isset($settings['responsiveness_probation'])) $settings['responsiveness_probation'] = 1; + + $settings['current_era_id'] = self::getCurrentERAId(); + + return $settings; + } + + public function getActiveMembers() { + $current_era_id = Helper::getCurrentERAId(); + $temp = DB::select(" + SELECT + a.public_key, + b.extra_status, + c.id, c.email, c.pseudonym, c.node_status, + d.status, d.extra_status as profile_extra_status + FROM all_node_data2 AS a + JOIN user_addresses AS b + ON a.public_key = b.public_address_node + JOIN users AS c + ON b.user_id = c.id + JOIN profile AS d + ON c.id = d.user_id + WHERE a.era_id = $current_era_id and c.email is not NULL and d.status = 'approved' + "); + return ($temp ?? []); + } + + public static function calculateUptime($baseObject, $public_address_node, $settings = null) { + if (!$settings) $settings = self::getSettings(); + + $current_era_id = (int) ($settings['current_era_id'] ?? 0); + $uptime_calc_size = (int) ($settings['uptime_calc_size'] ?? 1); + + $mbs = 0; + if (isset($baseObject->mbs)) { + $mbs = (float) ($baseObject->mbs ?? 0); + } else { + $temp = DB::select(" + SELECT mbs + FROM mbs + WHERE era_id = $current_era_id + "); + $mbs = (float) ($temp[0]->mbs ?? 0); + } + + $temp = DB::select(" + SELECT in_current_era + FROM all_node_data2 + WHERE public_key = '$public_address_node' + AND bid_total_staked_amount > $mbs + ORDER BY era_id DESC + LIMIT $uptime_calc_size + "); + if (!$temp) $temp = []; + + $window = count($temp); + $missed = 0; + foreach ($temp as $c) { + $in = (bool) ($c->in_current_era ?? 0); + if (!$in) { + $missed += 1; + } + } + + $uptime = (float) ($baseObject->uptime ?? 0); + if ($window > 0) { + $uptime = (float) (($uptime * ($window - $missed)) / $window); + } + + return round($uptime, 2); + } + + public static function calculateVariables($identifier, $public_address_node, $settings = null) { + if (!$settings) $settings = self::getSettings(); + + $current_era_id = (int) ($settings['current_era_id'] ?? 0); + + if ($identifier == 'good_standing_eras') { + $temp = DB::select(" + SELECT era_id + FROM all_node_data2 + WHERE public_key = '$public_address_node' + AND ( + in_current_era = 0 OR + bid_inactive = 1 + ) + ORDER BY era_id DESC + LIMIT 1 + "); + $value = $current_era_id - (int) ($temp[0]->era_id ?? 0); + if ($value > 0) return $value; + return 0; + } else if ($identifier == 'total_active_eras') { + $temp = DB::select(" + SELECT count(id) as tCount + FROM all_node_data2 + WHERE public_key = '$public_address_node' + AND in_current_era = 1 + AND bid_inactive = 0 + "); + return (int) ($temp[0]->tCount ?? 0); + } else if ($identifier == 'bad_marks_info') { + $temp = DB::select(" + SELECT era_id + FROM all_node_data2 + WHERE public_key = '$public_address_node' + AND ( + in_current_era = 0 OR + bid_inactive = 1 + ) + ORDER BY era_id DESC + "); + $total_bad_marks = count($temp ?? []); + $eras_since_bad_mark = $current_era_id - (int) ($temp[0]->era_id ?? 0); + return [ + 'total_bad_marks' => $total_bad_marks, + 'eras_since_bad_mark' => $eras_since_bad_mark + ]; + } else if ($identifier == 'min_era') { + $temp = DB::select(" + SELECT era_id + FROM all_node_data2 + WHERE public_key = '$public_address_node' + ORDER BY era_id ASC + LIMIT 1 + "); + return (int) ($temp[0]->era_id ?? 0); + } + return 0; + } + + public static function calculateBadMarksRevoke($baseObject, $public_address_node, $settings = null) { + if (!$settings) $settings = self::getSettings(); + + $current_era_id = (int) ($settings['current_era_id'] ?? 0); + $redmarks_revoke_calc_size = (int) ($settings['redmarks_revoke_calc_size'] ?? 1); + + $window = $current_era_id - $redmarks_revoke_calc_size; + if ($window < 0) $window = 0; + + $temp = DB::select(" + SELECT count(era_id) AS bad_marks + FROM all_node_data2 + WHERE public_key = '$public_address_node' + AND era_id > $window + AND ( + in_current_era = 0 OR + bid_inactive = 1 + ) + "); + if (!$temp) $temp = []; + + return (int) ($temp[0]->bad_marks ?? 0); + } + + public static function getCurrentERAId() { + $record = DB::select(" + SELECT era_id + FROM all_node_data2 + ORDER BY era_id DESC + LIMIT 1 + "); + if ($record && count($record) > 0) { + $current_era_id = (int) ($record[0]->era_id ?? 0); + return $current_era_id; + } + return 0; + } + + public static function getTotalScore($r, $max_delegators, $max_stake_amount) { + $uptime_rate = $fee_rate = $count_rate = $stake_rate = 25; + if (isset($r->uptime_rate)) $uptime_rate = (float) $r->uptime_rate; + if (isset($r->fee_rate)) $fee_rate = (float) $r->fee_rate; + if (isset($r->count_rate)) $count_rate = (float) $r->count_rate; + if (isset($r->stake_rate)) $stake_rate = (float) $r->stake_rate; + + $uptime_score = (float) ($uptime_rate * (float) $r->uptime / 100); + $uptime_score = $uptime_score < 0 ? 0 : $uptime_score; + + $fee_score = $fee_rate * (1 - (float) ((float) $r->bid_delegation_rate / 100)); + $fee_score = $fee_score < 0 ? 0 : $fee_score; + + $count_score = (float) ((float) $r->bid_delegators_count / $max_delegators) * $count_rate; + $count_score = $count_score < 0 ? 0 : $count_score; + + $stake_score = (float) ((float) $r->bid_total_staked_amount / $max_stake_amount) * $stake_rate; + $stake_score = $stake_score < 0 ? 0 : $stake_score; + + return $uptime_score + $fee_score + $count_score + $stake_score; + } + + public static function getRanking($current_era_id) { + $rankingData = []; + + $ranking = DB::select(" + SELECT + public_key, uptime, + bid_delegators_count, + bid_delegation_rate, + bid_total_staked_amount + FROM all_node_data2 + WHERE era_id = $current_era_id + AND in_current_era = 1 + AND in_next_era = 1 + AND in_auction = 1 + "); + $max_delegators = $max_stake_amount = 0; + + foreach ($ranking as $r) { + if ((int) $r->bid_delegators_count > $max_delegators) { + $max_delegators = (int) $r->bid_delegators_count; + } + if ((int) $r->bid_total_staked_amount > $max_stake_amount) { + $max_stake_amount = (int) $r->bid_total_staked_amount; + } + } + + foreach ($ranking as $r) { + $rankingData['ranking'][$r->public_key] = self::getTotalScore($r, $max_delegators, $max_stake_amount); + } + + uasort($rankingData['ranking'], function($x, $y) { + if ($x == $y) { + return 0; + } + return ($x > $y) ? -1 : 1; + }); + + $sorted_ranking = []; + $i = 1; + foreach ($rankingData['ranking'] as $public_key => $score) { + $sorted_ranking[$public_key] = $i; + $i += 1; + } + $rankingData['ranking'] = $sorted_ranking; + $rankingData['node_rank_total'] = count($sorted_ranking); + + return $rankingData; + } + public static function isAccessBlocked($user, $page) { if ($user->role == 'admin') return false; $flag = false; @@ -36,11 +323,10 @@ public static function isAccessBlocked($user, $page) { return $flag; } - public static function publicKeyToAccountHash($public_key) - { + public static function publicKeyToAccountHash($public_key) { $public_key = (string)$public_key; $first_byte = substr($public_key, 0, 2); - + if($first_byte === '01') { $algo = unpack('H*', 'ed25519'); } else { @@ -48,119 +334,136 @@ public static function publicKeyToAccountHash($public_key) } $algo = $algo[1] ?? ''; - + $blake2b = new Blake2b(); $account_hash = bin2hex($blake2b->hash(hex2bin($algo.'00'.substr($public_key, 2)))); return $account_hash; } - public static function getAccountInfoStandard($user) - { + public static function getStateRootHash() { + $get_block = 'casper-client get-block '; + $node_arg = '--node-address http://' . getenv('NODE_IP') . ':7777/rpc'; + + $json = shell_exec($get_block . $node_arg); + $json = json_decode($json); + + $state_root_hash = $json->result->block->header->state_root_hash ?? ''; + return $state_root_hash; + } + + public static function getAccountInfoStandard($user) { $vid = strtolower($user->public_address_node ?? ''); if (!$vid) return; + + try { + // convert to account hash + $account_hash = self::publicKeyToAccountHash($vid); + + $uid = $user->id ?? 0; + $pseudonym = $user->pseudonym ?? null; + + $account_info_urls_uref = getenv('ACCOUNT_INFO_STANDARD_URLS_UREF'); + $node_ip = 'http://' . getenv('NODE_IP') . ':7777'; + $casper_client = new RpcClient($node_ip); + $latest_block = $casper_client->getLatestBlock(); + $block_hash = $latest_block->getHash(); + $state_root_hash = $casper_client->getStateRootHash($block_hash); + $curl = curl_init(); + + $json_data = [ + 'id' => (int) time(), + 'jsonrpc' => '2.0', + 'method' => 'state_get_dictionary_item', + 'params' => [ + 'state_root_hash' => $state_root_hash, + 'dictionary_identifier' => [ + 'URef' => [ + 'seed_uref' => $account_info_urls_uref, + 'dictionary_item_key' => $account_hash, + ] + ] + ] + ]; + + curl_setopt($curl, CURLOPT_URL, $node_ip . '/rpc'); + curl_setopt($curl, CURLOPT_POST, true); + curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); + curl_setopt($curl, CURLOPT_POSTFIELDS, json_encode($json_data)); + curl_setopt($curl, CURLOPT_HTTPHEADER, [ + 'Accept: application/json', + 'Content-type: application/json', + ]); - // convert to account hash - $account_hash = self::publicKeyToAccountHash($vid); - - $uid = $user->id ?? 0; - $pseudonym = $user->pseudonym ?? null; - - $account_info_urls_uref = getenv('ACCOUNT_INFO_STANDARD_URLS_UREF'); - $node_ip = 'http://' . getenv('NODE_IP') . ':7777'; - $casper_client = new RpcClient($node_ip); - $latest_block = $casper_client->getLatestBlock(); - $block_hash = $latest_block->getHash(); - $state_root_hash = $casper_client->getStateRootHash($block_hash); - $curl = curl_init(); - - $json_data = array( - 'id' => (int) time(), - 'jsonrpc' => '2.0', - 'method' => 'state_get_dictionary_item', - 'params' => array( - 'state_root_hash' => $state_root_hash, - 'dictionary_identifier' => array( - 'URef' => array( - 'seed_uref' => $account_info_urls_uref, - 'dictionary_item_key' => $account_hash, - ) - ) - ) - ); - - curl_setopt($curl, CURLOPT_URL, $node_ip . '/rpc'); - curl_setopt($curl, CURLOPT_POST, true); - curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); - curl_setopt($curl, CURLOPT_POSTFIELDS, json_encode($json_data)); - curl_setopt($curl, CURLOPT_HTTPHEADER, array( - 'Accept: application/json', - 'Content-type: application/json', - )); - - $response = curl_exec($curl); - $decodedResponse = []; - if ($response) $decodedResponse = json_decode($response, true); - $parsed = $decodedResponse['result']['stored_value']['CLValue']['parsed'] ?? ''; - $json = array(); - - if($parsed) { - curl_setopt( - $curl, - CURLOPT_URL, - $parsed.'/.well-known/casper/account-info.casper.json' - ); - curl_setopt($curl, CURLOPT_POST, false); $response = curl_exec($curl); + $decodedResponse = []; - try { - $json = json_decode($response, true); - } catch (\Exception $e) { - $json = array(); + if ($response) { + $decodedResponse = json_decode($response, true); } - } - curl_close($curl); + $parsed = $decodedResponse['result']['stored_value']['CLValue']['parsed'] ?? ''; + $json = []; + + if($parsed) { + curl_setopt( + $curl, + CURLOPT_URL, + $parsed . '/.well-known/casper/account-info.casper.json' + ); + curl_setopt($curl, CURLOPT_POST, false); + $response = curl_exec($curl); + + try { + $json = json_decode($response, true); + } catch (\Exception $e) { + $json = []; + } + } - $blockchain_name = $json['owner']['name'] ?? null; - $blockchain_desc = $json['owner']['description'] ?? null; - $blockchain_logo = $json['owner']['branding']['logo']['png_256'] ?? null; - $profile = Profile::where('user_id', $uid)->first(); + curl_close($curl); - if ($profile && $json) { - if ($blockchain_name) { - $profile->blockchain_name = $blockchain_name; - } + $blockchain_name = $json['owner']['name'] ?? null; + $blockchain_desc = $json['owner']['description'] ?? null; + $blockchain_logo = $json['owner']['branding']['logo']['png_256'] ?? null; + $profile = Profile::where('user_id', $uid)->first(); - if ($blockchain_desc) { - $profile->blockchain_desc = $blockchain_desc; - } + if ($profile && $json) { + if ($blockchain_name) { + $profile->blockchain_name = $blockchain_name; + } - if ($blockchain_logo && $user->avatar == null) { - $user->avatar = $blockchain_logo; - $user->save(); - } + if ($blockchain_desc) { + $profile->blockchain_desc = $blockchain_desc; + } + + if ($blockchain_logo && $user->avatar == null) { + $user->avatar = $blockchain_logo; + $user->save(); + } - $profile->save(); - $shufti_profile = Shuftipro::where('user_id', $uid)->first(); - - if ( - $shufti_profile && - $shufti_profile->status == 'approved' && - $pseudonym - ) { - $shuft_status = $shufti_profile->status; - $reference_id = $shufti_profile->reference_id; - $hash = md5($pseudonym . $reference_id . $shuft_status); - $profile->casper_association_kyc_hash = $hash; $profile->save(); + $shufti_profile = Shuftipro::where('user_id', $uid)->first(); + + if ( + $shufti_profile && + $shufti_profile->status == 'approved' && + $pseudonym + ) { + $shuft_status = $shufti_profile->status; + $reference_id = $shufti_profile->reference_id; + $hash = md5($pseudonym . $reference_id . $shuft_status); + $profile->casper_association_kyc_hash = $hash; + $profile->save(); + } } + } catch (\Exception $ex) { + // } } // Get Token Price - public static function getTokenPrice() - { + public static function getTokenPrice() { $url = 'https://pro-api.coinmarketcap.com/v1/tools/price-conversion'; $apiKey = config('services.token_price.api_key'); @@ -174,107 +477,4 @@ public static function getTokenPrice() return $response->json(); } - - public static function getNodeInfo($user, $public_address_node = null) - { - if (!$public_address_node) $public_address_node = $user->public_address_node; - - $max_update_responsiveness = DB::select("SELECT max(update_responsiveness) as max_update_responsiveness FROM - ( - SELECT MAX(update_responsiveness) as update_responsiveness FROM metric - UNION - SELECT MAX(update_responsiveness) as update_responsiveness FROM node_info - ) AS results - ;"); - $max_update_responsiveness = $max_update_responsiveness[0]->max_update_responsiveness ?? 0; - - $max_peers = DB::select("SELECT max(peers) as max_peers FROM - ( - SELECT MAX(peers) as peers FROM metric - UNION - SELECT MAX(peers) as peers FROM node_info - ) AS results - ;"); - $max_peers = $max_peers[0]->max_peers ?? 0; - $max_block_height = Node::max('block_height'); - $max_uptime = DB::select("SELECT max(uptime) as max_uptime FROM - ( - SELECT MAX(uptime) as uptime FROM metric - UNION - SELECT MAX(uptime) as uptime FROM node_info - ) AS results - ;"); - $max_uptime = $max_uptime[0]->max_uptime ?? 0; - - $latest = Node::where('node_address', strtolower($public_address_node)) - ->whereNotnull('protocol_version') - ->orderBy('created_at', 'desc') - ->first(); - - if (!$latest) { - $latest = new Node(); - } - - $metric = Metric::where('user_id', $user->id)->first(); - - if (!$metric) { - $metric = new Metric(); - } - - $metric_block_height = $metric->block_height_average ? ($max_block_height - $metric->block_height_average) : null; - - $nodeInfo = NodeInfo::where('node_address', strtolower($public_address_node))->first(); - - if (!$nodeInfo) { - $nodeInfo = new NodeInfo(); - } - - $metric->avg_uptime = $nodeInfo->uptime ?? $metric->uptime ?? null; - $metric->avg_block_height_average = $nodeInfo->block_height ?? $metric_block_height; - $metric->avg_update_responsiveness = $nodeInfo->update_responsiveness ?? $metric->update_responsiveness ?? null; - $metric->avg_peers = $nodeInfo->peers ?? $metric->peers ?? null; - - $metric->max_peers = $max_peers; - $metric->max_update_responsiveness = $max_update_responsiveness; - $metric->max_block_height_average = $max_block_height; - $metric->max_uptime = $max_uptime; - - $metric->peers = $latest->peers ?? $metric->peers ?? null; - $metric->update_responsiveness = $latest->update_responsiveness ?? $metric->update_responsiveness ?? null; - $metric->block_height_average = $latest->block_height ?? $metric_block_height; - $metric->uptime = $nodeInfo->uptime ?? $metric->uptime ?? null; - - $monitoringCriteria = MonitoringCriteria::get(); - $nodeInfo = NodeInfo::where('node_address', strtolower($public_address_node))->first(); - $rank = $user->rank; - $delegators = 0; - $stake_amount = 0; - $self_staked_amount = 0; - $is_open_port = 0; - - if ($nodeInfo) { - $delegators = $nodeInfo->delegators_count; - $stake_amount = $nodeInfo->total_staked_amount; - $self_staked_amount = $nodeInfo->self_staked_amount; - $is_open_port = $nodeInfo->is_open_port; - } - - $mbs = NodeInfo::max('mbs'); - $metric->mbs = $mbs; - $metric->rank = $rank; - $metric->is_open_port = $is_open_port; - $metric->delegators = $delegators; - $metric->stake_amount = $stake_amount; - $metric->self_staked_amount = $self_staked_amount; - $metric['node_status'] = $user->node_status; - $metric['monitoring_criteria'] = $monitoringCriteria; - return $metric; - } - - public static function paginate($items, $perPage = 5, $page = null, $options = []) - { - $page = $page ?: (Paginator::resolveCurrentPage() ?: 1); - $items = $items instanceof Collection ? $items : Collection::make($items); - return new LengthAwarePaginator($items->forPage($page, $perPage), $items->count(), $perPage, $page, $options); - } } \ No newline at end of file diff --git a/app/Console/Kernel.php b/app/Console/Kernel.php index c6c45b75..b90fd1f6 100644 --- a/app/Console/Kernel.php +++ b/app/Console/Kernel.php @@ -24,38 +24,39 @@ class Kernel extends ConsoleKernel */ protected function schedule(Schedule $schedule) { - // $schedule->command('inspire')->hourly(); $schedule->command('ballot:check') - ->everyMinute() + ->everyTwoMinutes() ->runInBackground(); - /* - $schedule->command('shuftipro:check') - ->everyFiveMinutes() + + $schedule->command('ballot:check2') + ->hourly() + ->runInBackground(); + + $schedule->command('upgrade:check') + ->hourly() ->runInBackground(); - // ->withoutOverlapping(); - */ + $schedule->command('perk:check') ->everyThirtyMinutes() ->runInBackground(); + $schedule->command('notif:check') ->dailyAt('00:01') ->runInBackground(); + $schedule->command('node-status:check') ->everyFiveMinutes() ->runInBackground(); + $schedule->command('token-price:check') ->everyThirtyMinutes() ->runInBackground(); - $schedule->command('node-info') - ->everyFifteenMinutes() - ->runInBackground(); - $schedule->command('refresh:address') + + $schedule->command('historical-data') + ->withoutOverlapping() ->everyFiveMinutes() ->runInBackground(); - - /** - * Added by blockchainthomas. Cron for alerting admins of members stuck at KYC on a daily basis - */ + $schedule->command('kyc:report') ->dailyAt('10:02') ->runInBackground(); diff --git a/app/Helpers/helper.php b/app/Helpers/helper.php deleted file mode 100644 index 62044e23..00000000 --- a/app/Helpers/helper.php +++ /dev/null @@ -1,73 +0,0 @@ - $memory, - 'totalram' => $totalram, - 'usedmemInGB' => $usedmemInGB, - 'load' => $load, - ]; -} - -// Get Settings -function getSettings() -{ - // Get Settings - $settings = []; - $items = Setting::get(); - if ($items) { - foreach ($items as $item) { - $settings[$item->name] = $item->value; - } - } - return $settings; -} diff --git a/app/Http/Controllers/Api/V1/AdminController.php b/app/Http/Controllers/Api/V1/AdminController.php index 87c51f53..16a805cc 100644 --- a/app/Http/Controllers/Api/V1/AdminController.php +++ b/app/Http/Controllers/Api/V1/AdminController.php @@ -7,6 +7,9 @@ use App\Http\Controllers\Controller; use App\Http\EmailerHelper; +use App\Jobs\BallotNotification; +use App\Jobs\NewUpgradeNotification; + use App\Mail\AdminAlert; use App\Mail\ResetKYC; use App\Mail\ResetPasswordMail; @@ -41,6 +44,13 @@ use App\Models\VerifyUser; use App\Models\Vote; use App\Models\VoteResult; +use App\Models\ContactRecipient; +use App\Models\AllNodeData2; +use App\Models\ReinstatementHistory; +use App\Models\Upgrade; +use App\Models\UpgradeUser; + +use App\Services\NodeHelper; use Illuminate\Http\Request; use Illuminate\Http\Response; @@ -59,166 +69,916 @@ class AdminController extends Controller { - public function getUsers(Request $request) + public function getUpgrades(Request $request) { + $upgrades = Upgrade::orderBy('id', 'asc')->get(); + return $this->successResponse($upgrades); + } + + public function getSingleUpgrade($id) { + $upgrade = Upgrade::find($id); + if ($upgrade) { + return $this->successResponse($upgrade); + } + return $this->errorResponse('The Upgrade does not exist', Response::HTTP_BAD_REQUEST); + } + + public function createUpgrade(Request $request) { + $validator = Validator::make($request->all(), [ + 'version' => 'required|string|max:70', + 'activation_era' => 'required|integer', + 'activation_date' => 'required|date_format:Y-m-d', + 'link' => 'required|url|max:255', + 'notes' => 'required', + ]); + if ($validator->fails()) { + return $this->validateResponse($validator->errors()); + } + + $version = $request->version; + $link = $request->link; + $notes = $request->notes; + $activation_era = (int) $request->activation_era; + $activation_date = $request->activation_date; + $activation_datetime = $activation_date . ' 00:00:00'; + + if ($activation_era < 1) { + return $this->errorResponse('Activation ERA must be greater than 1', Response::HTTP_BAD_REQUEST); + } + + $temp = DB::select(" + SELECT + MAX(activation_era) as era + FROM upgrades + "); + $maxERA = (int) ($temp[0]->era ?? 0); + + if ($activation_era <= $maxERA) { + return $this->errorResponse('Activation ERA must be greater than ' . $maxERA, Response::HTTP_BAD_REQUEST); + } + + $upgradeRecord = Upgrade::where('version', $version)->first(); + if ($upgradeRecord) { + return $this->errorResponse('The Version No is already used', Response::HTTP_BAD_REQUEST); + } + + $upgradeRecord = new Upgrade; + $upgradeRecord->version = $version; + $upgradeRecord->activation_era = $activation_era; + $upgradeRecord->activation_date = $activation_date; + $upgradeRecord->activation_datetime = $activation_datetime; + $upgradeRecord->link = $link; + $upgradeRecord->notes = $notes; + $upgradeRecord->save(); + + NewUpgradeNotification::dispatch($upgradeRecord)->onQueue('default_long'); + + return $this->successResponse($upgradeRecord); + } + + public function updateUpgrade($id, Request $request) { + $validator = Validator::make($request->all(), [ + 'version' => 'required|string|max:70', + 'activation_era' => 'required|integer', + 'activation_date' => 'required|date_format:Y-m-d', + 'link' => 'required|url|max:255', + 'notes' => 'required', + ]); + if ($validator->fails()) { + return $this->validateResponse($validator->errors()); + } + + $upgradeRecord = Upgrade::find($id); + if (!$upgradeRecord) { + return $this->errorResponse('The Upgrade does not exist', Response::HTTP_BAD_REQUEST); + } + + $version = $request->version; + $link = $request->link; + $notes = $request->notes; + $activation_era = (int) $request->activation_era; + $activation_date = $request->activation_date; + $activation_datetime = $activation_date . ' 00:00:00'; + + if ($activation_era < 1) { + return $this->errorResponse('Activation ERA must be greater than 1', Response::HTTP_BAD_REQUEST); + } + + $temp = DB::select(" + SELECT + MAX(activation_era) as era + FROM upgrades + where id != $id + "); + $maxERA = (int) ($temp[0]->era ?? 0); + + if ($activation_era <= $maxERA) { + return $this->errorResponse('Activation ERA must be greater than ' . $maxERA, Response::HTTP_BAD_REQUEST); + } + + $upgradeRecordTemp = Upgrade::where('version', $version) + ->where('id', '!=', $id) + ->first(); + if ($upgradeRecordTemp) { + return $this->errorResponse('The Version No is already used', Response::HTTP_BAD_REQUEST); + } + + $upgradeRecord->version = $version; + $upgradeRecord->activation_era = $activation_era; + $upgradeRecord->activation_date = $activation_date; + $upgradeRecord->activation_datetime = $activation_datetime; + $upgradeRecord->link = $link; + $upgradeRecord->notes = $notes; + $upgradeRecord->save(); + + return $this->successResponse($upgradeRecord); + } + + public function deleteUpgrade($id) { + $user = auth()->user(); + if (!$user || $user->role != 'admin') { + return $this->errorResponse(__('api.error.not_found'), Response::HTTP_NOT_FOUND); + } + + UpgradeUser::where('upgrade_id', $id)->delete(); + Upgrade::where('id', $id)->delete(); + + return $this->metaSuccess(); + } + + public function allErasUser($id) { + $user = User::where('id', $id)->first(); + $user_id = $id; + + if (!$user || $user->role == 'admin') { + return $this->errorResponse(__('api.error.not_found'), Response::HTTP_NOT_FOUND); + } + + $settings = Helper::getSettings(); + $current_era_id = (int) ($settings['current_era_id'] ?? 0); + + $return = [ + 'eras' => [], + 'addresses' => [] + ]; + + $uptime_calc_size = isset($settings['uptime_calc_size']) ? (int) $settings['uptime_calc_size'] : 1; + + $era_minus_360 = $current_era_id - $uptime_calc_size; + if ($era_minus_360 < 1) { + $era_minus_360 = 1; + } + + // get addresses data + $addresses = DB::select(" + SELECT + a.public_key + FROM all_node_data2 AS a + JOIN user_addresses AS b + ON a.public_key = b.public_address_node + WHERE a.era_id = $current_era_id + AND b.user_id = $user_id + ORDER BY a.era_id DESC + "); + if (!$addresses) $addresses = []; + + foreach ($addresses as $address) { + $return['addresses'][] = $address->public_key; + } + + $eras = DB::select(" + SELECT + a.public_key, a.era_id, a.created_at, + a.in_current_era, a.in_auction, + a.bid_inactive, a.uptime + FROM all_node_data2 AS a + JOIN user_addresses + ON a.public_key = user_addresses.public_address_node + JOIN users + ON user_addresses.user_id = users.id + WHERE users.id = $user_id + AND era_id > $era_minus_360 + ORDER BY a.era_id DESC + "); + if (!$eras) $eras = []; + + $sorted_eras = []; + + // for each node address's era + foreach ($eras as $era) { + $era_id = $era->era_id ?? 0; + $era_start_time = $era->created_at ?? ''; + $public_key = $era->public_key; + + if (!isset($sorted_eras[$era_id])) { + $sorted_eras[$era_id] = [ + 'era_start_time' => $era_start_time, + 'addresses' => [] + ]; + } + + $sorted_eras[$era_id]['addresses'][$public_key] = [ + 'in_pool' => $era->in_auction, + 'rewards' => $era->uptime, + ]; + } + + $return['eras'] = $sorted_eras; + + return $this->successResponse($return); + } + + public function allEras() { + $settings = Helper::getSettings(); + $current_era_id = (int) ($settings['current_era_id'] ?? 0); + + // define return object + $return = [ + 'addresses' => [], + 'users' => [] + ]; + + // get addresses data + $addresses = DB::select(" + SELECT + a.public_key, a.uptime, b.user_id + FROM all_node_data2 AS a + JOIN user_addresses AS b + ON a.public_key = b.public_address_node + WHERE a.era_id = $current_era_id + "); + if (!$addresses) $addresses = []; + + // for each member's node address + foreach ($addresses as $address) { + $p = $address->public_key ?? ''; + + $badMarkValues = Helper::calculateVariables('bad_marks_info', $p, $settings); + $total_bad_marks = (int) ($badMarkValues['total_bad_marks'] ?? 0); + $eras_since_bad_mark = (int) ($badMarkValues['eras_since_bad_mark'] ?? $current_era_id); + + $min_era_id = Helper::calculateVariables('min_era', $p, $settings); + $eras_active = $current_era_id - $min_era_id; + + $historical_performance = Helper::calculateUptime($address, $p, $settings); + + $return['addresses'][$p] = [ + 'uptime' => $historical_performance, + 'eras_active' => $eras_active, + 'eras_since_bad_mark' => $eras_since_bad_mark, + 'total_bad_marks' => $total_bad_marks + ]; + } + + $users = DB::select(" + SELECT + a.id, a.first_name, a.last_name, a.pseudonym + FROM users AS a + WHERE a.role = 'member' + AND a.has_address = 1 + AND a.banned = 0; + "); + if (!$users) $users = []; + + foreach ($users as $user) { + $return['users'][] = [ + 'user_id' => $user->id, + 'name' => $user->first_name . ' ' . $user->last_name, + 'pseudonym' => $user->pseudonym, + ]; + } + + return $this->successResponse($return); + } + + public function getNodesPage() { + $settings = Helper::getSettings(); + $current_era_id = (int) ($settings['current_era_id'] ?? 0); + + $return = [ + 'mbs' => 0, + 'ranking' => [], + 'addresses' => [] + ]; + + $nodeHelper = new NodeHelper(); + + $rankingData = Helper::getRanking($current_era_id); + + $return['ranking'] = $rankingData['ranking']; + + // get user addresses + $addresses = DB::select(" + SELECT + a.public_key, a.bid_delegators_count, + a.bid_total_staked_amount, a.bid_self_staked_amount, + a.uptime, a.bid_inactive, a.in_current_era, + a.port8888_peers AS peers + FROM all_node_data2 AS a + JOIN user_addresses AS b + ON a.public_key = b.public_address_node + JOIN users AS c + ON b.user_id = c.id + WHERE a.era_id = $current_era_id + "); + if (!$addresses) $addresses = []; + + // for each member's node address + foreach ($addresses as $address) { + $a = $address->public_key ?? ''; + + $badMarkValues = Helper::calculateVariables('bad_marks_info', $a, $settings); + $total_bad_marks = (int) ($badMarkValues['total_bad_marks'] ?? 0); + $eras_since_bad_mark = (int) ($badMarkValues['eras_since_bad_mark'] ?? $current_era_id); + + $min_era_id = Helper::calculateVariables('min_era', $a, $settings); + $total_eras = $current_era_id - $min_era_id; + + $historical_performance = Helper::calculateUptime($address, $a, $settings); + + // Calc earning + $one_day_ago = Carbon::now('UTC')->subHours(24); + $temp = DB::select(" + SELECT bid_self_staked_amount + FROM all_node_data2 + WHERE public_key = '$a' + AND created_at < '$one_day_ago' + ORDER BY era_id DESC + LIMIT 1 + "); + if (!$temp) $temp = []; + + $daily_earning = (float) ($temp[0]->bid_self_staked_amount ?? 0); + $daily_earning = (float) $address->bid_self_staked_amount - $daily_earning; + $daily_earning = $daily_earning < 0 ? 0 : $daily_earning; + + $earning_day = $nodeHelper->getValidatorRewards($a, 'day'); + $earning_week = $nodeHelper->getValidatorRewards($a, 'week'); + $earning_month = $nodeHelper->getValidatorRewards($a, 'month'); + $earning_year = $nodeHelper->getValidatorRewards($a, 'year'); + + if ( + $address->in_current_era == 0 || + $address->bid_inactive == 1 + ) { + $failing = 1; + } else { + $failing = 0; + } + + $return['addresses'][$a] = [ + 'stake_amount' => $address->bid_total_staked_amount, + 'delegators' => $address->bid_delegators_count, + 'uptime' => $historical_performance, + 'update_responsiveness' => 100, + 'peers' => $address->peers, + 'daily_earning' => $daily_earning, + 'total_eras' => $total_eras, + 'eras_since_bad_mark' => $eras_since_bad_mark, + 'total_bad_marks' => $total_bad_marks, + 'failing' => $failing, + 'validator_rewards' => [ + 'day' => $earning_day, + 'week' => $earning_week, + 'month' => $earning_month, + 'year' => $earning_year + ] + ]; + } + + // get mbs + $temp = DB::select(" + SELECT mbs + FROM mbs + ORDER BY era_id DESC + LIMIT 1 + "); + $return['mbs'] = (int) ($temp[0]->mbs ?? 0); + + return $this->successResponse($return); + } + + public function getActiveReinstatements() { - $limit = $request->limit ?? 50; - $sort_key = $request->sort_key ?? ''; - $sort_direction = $request->sort_direction ?? ''; - if (!$sort_key) $sort_key = 'created_at'; - if (!$sort_direction) $sort_direction = 'desc'; - $users = User::where('role', 'member') - ->with(['profile']) - ->leftJoin('node_info', 'users.public_address_node', '=', 'node_info.node_address') - ->select([ - 'users.*', - 'node_info.delegation_rate', - 'node_info.delegators_count', - 'node_info.self_staked_amount', - 'node_info.total_staked_amount', - ]) + $items = Profile::with('user') + ->has('user') + ->where('extra_status', 'Suspended') + ->where('reactivation_requested', true) + ->whereNotNull('reactivation_requested_at') + ->orderBy('reactivation_requested_at', 'desc') ->get(); - foreach ($users as $user) { - $status = 'Not Verified'; - if ($user->profile && $user->profile->status == 'approved') { - $status = 'Verified'; - if ($user->profile->extra_status) - $status = $user->profile->extra_status; + return $this->successResponse($items); + } + + public function getHistoryReinstatements() + { + $items = ReinstatementHistory::with('user') + ->has('user') + ->whereNotNull('decision_at') + ->orderBy('decision_at', 'desc') + ->get(); + return $this->successResponse($items); + } + + public function revokeUser($id) + { + $user = User::with('profile') + ->has('profile') + ->where('id', $id) + ->where('role', 'member') + ->first(); + + if ($user && $user->profile->status == 'approved' && $user->profile->extra_status != 'Suspended') { + $user->profile->extra_status = 'Suspended'; + $user->profile->revoke_reason = 'Admin action'; + $user->profile->revoke_at = Carbon::now('UTC'); + $user->profile->reactivation_reason = null; + $user->profile->reactivation_requested = null; + $user->profile->reactivation_requested_at = null; + $user->profile->save(); + + return $this->metaSuccess(); + } + + return $this->errorResponse('Fail Revoke User', Response::HTTP_BAD_REQUEST); + } + + public function reactivateUser($id) + { + $user = User::with('profile') + ->has('profile') + ->where('id', $id) + ->where('role', 'member') + ->first(); + + if ( + $user && + $user->profile->status == 'approved' && + $user->profile->extra_status == 'Suspended' && + $user->profile->revoke_reason && + $user->profile->revoke_at + ) { + $user->profile->extra_status = null; + $user->profile->revoke_reason = null; + $user->profile->revoke_at = null; + $user->profile->reactivation_reason = null; + $user->profile->reactivation_requested = null; + $user->profile->reactivation_requested_at = null; + $user->profile->save(); + + return $this->metaSuccess(); + } + + return $this->errorResponse('Fail Reactivate User', Response::HTTP_BAD_REQUEST); + } + + public function approveReinstatement(Request $request) + { + $profileId = (int) ($request->profileId ?? 0); + $profile = Profile::find($profileId); + + if (!$profile) { + return $this->errorResponse(__('api.error.not_found'), Response::HTTP_NOT_FOUND); + } + + if ($profile->extra_status != 'Suspended' || !$profile->reactivation_requested) { + return $this->errorResponse(__('api.error.not_found'), Response::HTTP_NOT_FOUND); + } + + $userId = (int) $profile->user_id; + $revoke_at = $profile->revoke_at; + $revoke_reason = $profile->revoke_reason; + $reactivation_reason = $profile->reactivation_reason; + $reactivation_requested_at = $profile->reactivation_requested_at; + + if (!$revoke_at || !$reactivation_requested_at) { + return $this->errorResponse(__('api.error.not_found'), Response::HTTP_NOT_FOUND); + } + + $historyRecord = ReinstatementHistory::where('revoke_at', $revoke_at) + ->where('reactivation_requested_at', $reactivation_requested_at) + ->where('user_id', $userId) + ->first(); + if (!$historyRecord) { + $historyRecord = new ReinstatementHistory; + $historyRecord->user_id = $userId; + $historyRecord->revoke_at = $revoke_at; + $historyRecord->revoke_reason = $revoke_reason; + $historyRecord->reactivation_reason = $reactivation_reason; + $historyRecord->reactivation_requested_at = $reactivation_requested_at; + $historyRecord->decision = true; + $historyRecord->decision_at = Carbon::now('UTC'); + $historyRecord->save(); + } + + $profile->extra_status = null; + $profile->revoke_at = null; + $profile->revoke_reason = null; + $profile->reactivation_reason = null; + $profile->reactivation_requested = null; + $profile->reactivation_requested_at = null; + $profile->save(); + + $this->metaSuccess(); + } + + public function rejectReinstatement(Request $request) + { + $profileId = (int) ($request->profileId ?? 0); + $profile = Profile::find($profileId); + + if (!$profile) { + return $this->errorResponse(__('api.error.not_found'), Response::HTTP_NOT_FOUND); + } + + if ($profile->extra_status != 'Suspended' || !$profile->reactivation_requested) { + return $this->errorResponse(__('api.error.not_found'), Response::HTTP_NOT_FOUND); + } + + $userId = (int) $profile->user_id; + $revoke_at = $profile->revoke_at; + $revoke_reason = $profile->revoke_reason; + $reactivation_reason = $profile->reactivation_reason; + $reactivation_requested_at = $profile->reactivation_requested_at; + + if (!$revoke_at || !$reactivation_requested_at) { + return $this->errorResponse(__('api.error.not_found'), Response::HTTP_NOT_FOUND); + } + + $historyRecord = ReinstatementHistory::where('revoke_at', $revoke_at) + ->where('reactivation_requested_at', $reactivation_requested_at) + ->where('user_id', $userId) + ->first(); + if (!$historyRecord) { + $historyRecord = new ReinstatementHistory; + $historyRecord->user_id = $userId; + $historyRecord->revoke_at = $revoke_at; + $historyRecord->revoke_reason = $revoke_reason; + $historyRecord->reactivation_reason = $reactivation_reason; + $historyRecord->reactivation_requested_at = $reactivation_requested_at; + $historyRecord->decision = false; + $historyRecord->decision_at = Carbon::now('UTC'); + $historyRecord->save(); + } + + $profile->reactivation_reason = null; + $profile->reactivation_requested = null; + $profile->reactivation_requested_at = null; + $profile->save(); + + $this->metaSuccess(); + } + + public function getUsers(Request $request) + { + $current_era_id = Helper::getCurrentERAId(); + + $query = " + SELECT + a.id, a.first_name, a.last_name, a.email, + a.pseudonym, a.telegram, a.email_verified_at, + a.entity_name, a.last_login_at, a.created_at, + a.signature_request_id, a.node_status, a.node_verified_at, + a.member_status, a.kyc_verified_at, + b.dob, b.country_citizenship, b.country_residence, + b.status AS profile_status, b.extra_status, b.revoke_reason, + b.type, b.casper_association_kyc_hash, + b.blockchain_name, b.blockchain_desc + FROM users AS a + LEFT JOIN profile AS b + ON a.id = b.user_id + WHERE a.role = 'member' + "; + + $sort_key = $request->get('sort_key'); + $sort_direction = $request->get('sort_direction'); + + if ($sort_key && $sort_direction) { + switch ($sort_key) { + case 'id': + $sort_key = 'a.id'; + break; + case 'membership_status': + $sort_key = 'b.status'; + break; + case 'node_status': + $sort_key = 'a.node_status'; + break; + case 'email': + $sort_key = 'a.email'; + break; + case 'entity_name': + $sort_key = 'a.entity_name'; + break; + case 'full_name': + $sort_key = 'a.first_name'; + break; + case 'created_at': + $sort_key = 'a.created_at'; + break; + default: + $sort_key = 'a.id'; + break; + } + $query .= " ORDER BY " . $sort_key . " " . $sort_direction; + } else { + $query .= " ORDER BY a.id desc"; + } + + $users = DB::select($query); + + if ($users) { + foreach ($users as &$user) { + $status = 'Not Verified'; + + if ($user->profile_status == 'approved') { + $status = 'Verified'; + if ($user->extra_status) { + $status = $user->extra_status; + if ($user->extra_status == 'Suspended') { + $status = 'Revoked'; + } + } + } + + $user->membership_status = $status; + $userId = (int) $user->id; + + $temp = DB::select(" + SELECT sum(a.bid_self_staked_amount) as self_staked_amount + FROM all_node_data2 as a + JOIN user_addresses as b ON b.public_address_node = a.public_key + WHERE b.user_id = $userId and a.era_id = $current_era_id + "); + + $self_staked_amount = (float) ($temp[0]->self_staked_amount ?? 0); + $user->self_staked_amount = round($self_staked_amount, 2); } - $user->membership_status = $status; } - if ($sort_direction == 'desc') $users = $users->sortByDesc($sort_key)->values(); - else $users = $users->sortBy($sort_key)->values(); - $users = Helper::paginate($users, $limit, $request->page); - $users = $users->toArray(); - $users['data'] = (collect($users['data'])->values()); + return $this->successResponse($users); } public function getUserDetail($id) { $user = User::where('id', $id)->first(); - if (!$user || $user->role == 'admin') + if (!$user || $user->role == 'admin') { return $this->errorResponse(__('api.error.not_found'), Response::HTTP_NOT_FOUND); + } $user = $user->load(['pagePermissions', 'profile', 'shuftipro', 'shuftiproTemp']); $status = 'Not Verified'; if ($user->profile && $user->profile->status == 'approved') { $status = 'Verified'; - if ($user->profile->extra_status) + if ($user->profile->extra_status) { $status = $user->profile->extra_status; + if ($user->profile->extra_status == 'Suspended') { + $status = 'Revoked'; + if ($user->profile->revoke_reason) { + $status = 'Revoked for ' . $user->profile->revoke_reason; + } + } + } } + $user->membership_status = $status; - $user->metric = Helper::getNodeInfo($user); + + $addresses = $user->addresses ?? []; + + $settings = Helper::getSettings(); + $current_era_id = (int) ($settings['current_era_id'] ?? 0); + + foreach ($addresses as &$addressItem) { + $temp = AllNodeData2::select([ + 'uptime', + 'bid_delegators_count', + 'bid_delegation_rate', + 'bid_self_staked_amount', + 'bid_total_staked_amount' + ]) + ->where('public_key', $addressItem->public_address_node) + ->where('era_id', $current_era_id) + ->orderBy('id', 'desc') + ->first() + ->toArray(); + if ($temp) { + foreach ($temp as $key => $value) { + if ($key == 'uptime') $value = round((float) $value, 2); + $addressItem->$key = $value; + } + $addressItem->update_responsiveness = 100; + $p = $addressItem->public_address_node; + + $historical_performance = Helper::calculateUptime($addressItem, $p, $settings); + $addressItem->uptime = $historical_performance; + + $badMarkValues = Helper::calculateVariables('bad_marks_info', $p, $settings); + $total_bad_marks = (int) ($badMarkValues['total_bad_marks'] ?? 0); + $eras_since_bad_mark = (int) ($badMarkValues['eras_since_bad_mark'] ?? $current_era_id); + + $min_era_id = Helper::calculateVariables('min_era', $p, $settings); + $eras_active = $current_era_id - $min_era_id; + + $addressItem->eras_since_bad_mark = $eras_since_bad_mark; + $addressItem->total_bad_marks = $total_bad_marks; + $addressItem->eras_active = $eras_active; + } + } + + $user->addresses = $addresses; + return $this->successResponse($user); } public function infoDashboard(Request $request) { + $current_era_id = Helper::getCurrentERAId(); + + $return = [ + 'total_users' => 0, + 'total_stake' => 0, + 'total_delegators' => 0, + 'avg_uptime' => 0, + 'avg_responsiveness' => 0, + 'new_users_ready' => 0, + 'id_to_review' => 0, + 'perks_active' => 0, + 'perks_views' => 0, + 'new_comments' => 0, + 'new_threads' => 0 + ]; + + $temp = DB::select(" + SELECT count(pseudonym) as totalCount + FROM users + WHERE role = 'member' + "); + $total_users = (int) ($temp[0]->totalCount ?? 0); + + $temp = DB::select(" + SELECT + SUM(a.bid_total_staked_amount) as totalSum + FROM all_node_data2 AS a + LEFT JOIN user_addresses AS b + ON a.public_key = b.public_address_node + WHERE a.era_id = $current_era_id + AND b.user_id IS NOT NULL + "); + $total_stake = (int) ($temp[0]->totalSum ?? 0); + + $temp = DB::select(" + SELECT + SUM(a.bid_delegators_count) as totalSum + FROM all_node_data2 AS a + LEFT JOIN user_addresses AS b + ON a.public_key = b.public_address_node + WHERE a.era_id = $current_era_id + AND b.user_id IS NOT NULL + "); + $total_delegators = (int) ($temp[0]->totalSum ?? 0); + + $temp = DB::select(" + SELECT + SUM(a.uptime) AS numerator, + COUNT(a.uptime) AS denominator + FROM all_node_data2 AS a + LEFT JOIN user_addresses AS b + ON a.public_key = b.public_address_node + WHERE era_id = $current_era_id + AND b.user_id IS NOT NULL + "); + $denominator = (int) ($temp[0]->denominator ?? 1); + if (!$denominator) $denominator = 1; + $avg_uptime = (float) (($temp[0]->numerator ?? 0) / $denominator); + $avg_uptime = round($avg_uptime, 2); + + $avg_responsiveness = 100; + + // get new users ready for admin review + $new_users_ready = User::where('banned', 0) + ->where('role', 'member') + ->where(function ($q) { + $q->where('users.node_verified_at', null) + ->orWhere('users.letter_verified_at', null) + ->orWhere('users.signature_request_id', null); + })->count(); + + // get new users ready for kyc review + $id_to_review = User::where('users.role', 'member') + ->where('banned', 0) + ->join('profile', function ($query) { + $query->on('profile.user_id', '=', 'users.id') + ->where('profile.status', 'pending'); + }) + ->join('shuftipro', 'shuftipro.user_id', '=', 'users.id') + ->count(); + $timeframe_perk = $request->timeframe_perk ?? 'last_7days'; $timeframe_comments = $request->timeframe_comments ?? 'last_7days'; $timeframe_discussions = $request->timeframe_discussions ?? 'last_7days'; + // last_24hs, last_7days, last_30days, last_year - if ($timeframe_perk == 'last_24hs') - $timeframe_perk = Carbon::now('UTC')->subHours(24); - else if ($timeframe_perk == 'last_30days') - $timeframe_perk = Carbon::now('UTC')->subDays(30); - else if ($timeframe_perk == 'last_year') - $timeframe_perk = Carbon::now('UTC')->subYear(); - else - $timeframe_perk = Carbon::now('UTC')->subDays(7); - - if ($timeframe_comments == 'last_24hs') - $timeframe_comments = Carbon::now('UTC')->subHours(24); - else if ($timeframe_comments == 'last_30days') { - $timeframe_comments = Carbon::now('UTC')->subDays(30); + if ($timeframe_perk == 'last_24hs') { + $timeframe_perk = Carbon::now('UTC')->subHours(24); + } else if ($timeframe_perk == 'last_30days') { + $timeframe_perk = Carbon::now('UTC')->subDays(30); + } else if ($timeframe_perk == 'last_year') { + $timeframe_perk = Carbon::now('UTC')->subYear(); + } else { + $timeframe_perk = Carbon::now('UTC')->subDays(7); + } + + if ($timeframe_comments == 'last_24hs') { + $timeframe_comments = Carbon::now('UTC')->subHours(24); + } else if ($timeframe_comments == 'last_30days') { + $timeframe_comments = Carbon::now('UTC')->subDays(30); } else if ($timeframe_comments == 'last_year') { - $timeframe_comments = Carbon::now('UTC')->subYear(); + $timeframe_comments = Carbon::now('UTC')->subYear(); } else { - $timeframe_comments = Carbon::now('UTC')->subDays(7); + $timeframe_comments = Carbon::now('UTC')->subDays(7); } if ($timeframe_discussions == 'last_24hs') { - $timeframe_discussions = Carbon::now('UTC')->subHours(24); + $timeframe_discussions = Carbon::now('UTC')->subHours(24); } else if ($timeframe_discussions == 'last_30days') { - $timeframe_discussions = Carbon::now('UTC')->subDays(30); + $timeframe_discussions = Carbon::now('UTC')->subDays(30); } else if ($timeframe_discussions == 'last_year') { - $timeframe_discussions = Carbon::now('UTC')->subYear(); + $timeframe_discussions = Carbon::now('UTC')->subYear(); } else { - $timeframe_discussions = Carbon::now('UTC')->subDays(7); + $timeframe_discussions = Carbon::now('UTC')->subDays(7); } - $totalUser = User::where('role', 'member')->count(); - $toTalStake = NodeInfo::sum('total_staked_amount'); - $totalDelagateer = NodeInfo::sum('delegators_count'); - $totalNewUserReady = User::where('banned', 0) - ->where('role', 'member') - ->where(function ($q) { - $q->where('users.node_verified_at', null) - ->orWhere('users.letter_verified_at', null) - ->orWhere('users.signature_request_id', null); - })->count(); + // get active perks + $perks_active = Perk::where('status', 'active') + ->where('created_at', '>=', $timeframe_perk) + ->count(); + + // get total perk views + $perks_views = Perk::where('status', 'active') + ->where('created_at', '>=', $timeframe_perk) + ->sum('total_views'); + + // get comments + $new_comments = DiscussionComment::where('created_at', '>=', $timeframe_comments)->count(); + + // get discussions + $new_threads = Discussion::where('created_at', '>=', $timeframe_discussions)->count(); + + $return['total_users'] = $total_users; + $return['total_stake'] = $total_stake; + $return['total_delegators'] = $total_delegators; + $return['avg_uptime'] = $avg_uptime; + $return['avg_responsiveness'] = $avg_responsiveness; + $return['new_users_ready'] = $new_users_ready; + $return['id_to_review'] = $id_to_review; + $return['perks_active'] = $perks_active; + $return['perks_views'] = $perks_views; + $return['new_comments'] = $new_comments; + $return['new_threads'] = $new_threads; + + return $this->successResponse($return); + } + + public function bypassApproveKYC($user_id) + { + $user_id = (int) $user_id; + $user = User::find($user_id); + $now = Carbon::now('UTC'); + $admin_user = auth()->user(); + + if ($user && $user->role == 'member') { + $user->kyc_verified_at = $now; + $user->approve_at = $now; + $user->kyc_bypass_approval = 1; + $user->save(); + + $profile = Profile::where('user_id', $user_id)->first(); - $totalUserVerification = User::where('users.role', 'member') - ->where('banned', 0) - ->join('profile', function ($query) { - $query->on('profile.user_id', '=', 'users.id') - ->where('profile.status', 'pending'); - }) - ->join('shuftipro', 'shuftipro.user_id', '=', 'users.id') - ->count(); - $totalFailNode = User::where('banned', 0)->whereNotNull('public_address_node')->where('is_fail_node', 1)->count(); - - $totalPerksActive = Perk::where('status', 'active')->where('created_at', '>=', $timeframe_perk)->count(); - $totalPerksViews = Perk::where('status', 'active')->where('created_at', '>=', $timeframe_perk)->sum('total_views'); - - $totalNewComments = DiscussionComment::where('created_at', '>=', $timeframe_comments)->count(); - $totalNewDiscussions = Discussion::where('created_at', '>=', $timeframe_discussions)->count(); - - $uptime_nodes = NodeInfo::whereNotNull('uptime')->pluck('uptime'); - $uptime_metrics = Metric::whereNotNull('uptime')->pluck('uptime'); - - $blocks_hight_nodes = NodeInfo::whereNotNull('block_height_average')->pluck('block_height_average'); - $blocks_hight_metrics = Metric::whereNotNull('block_height_average')->pluck('block_height_average'); - $total_blocks_hight_metrics = 0; - $base_block = 10; - foreach ($blocks_hight_metrics as $value) { - $avg = ($base_block - $value) * 10; - if ($avg > 0) { - $total_blocks_hight_metrics += $avg; + if (!$profile) { + $profile = new Profile; + $profile->user_id = $user_id; + $profile->first_name = $user->first_name; + $profile->last_name = $user->last_name; + $profile->type = $user->type; } - } - $responsiveness_nodes = NodeInfo::whereNotNull('update_responsiveness')->pluck('update_responsiveness'); - $responsiveness_metrics = Metric::whereNotNull('update_responsiveness')->pluck('update_responsiveness'); - - $countUptime = count($uptime_nodes) + count($uptime_metrics) > 0 ? count($uptime_nodes) + count($uptime_metrics) : 1; - $count_responsiveness_nodes = count($responsiveness_nodes) + count($responsiveness_metrics); - $count_responsiveness_nodes = $count_responsiveness_nodes > 0 ? $count_responsiveness_nodes : 1; - $count_blocks_hight = (count($blocks_hight_nodes) + count($blocks_hight_metrics)) > 0 ? (count($blocks_hight_nodes) + count($blocks_hight_metrics)) : 1; - $response['totalUser'] = $totalUser; - $response['totalStake'] = $toTalStake; - $response['totalDelegators'] = $totalDelagateer; - $response['totalNewUserReady'] = $totalNewUserReady; - $response['totalUserVerification'] = $totalUserVerification; - $response['totalFailNode'] = $totalFailNode; - $response['totalPerksActive'] = $totalPerksActive; - $response['totalPerksViews'] = $totalPerksViews; - $response['totalNewComments'] = $totalNewComments; - $response['totalNewDiscussions'] = $totalNewDiscussions; - $response['avgUptime'] = ($uptime_nodes->sum() + $uptime_metrics->sum()) / $countUptime; - $response['avgBlockHeightAverage'] = ($blocks_hight_nodes->sum() + $total_blocks_hight_metrics) / $count_blocks_hight; - $response['avgUpdateResponsiveness'] = ($responsiveness_nodes->sum() + $responsiveness_metrics->sum()) / $count_responsiveness_nodes; - return $this->successResponse($response); - } + $profile->status = 'approved'; + $profile->save(); + $shuftipro = Shuftipro::where('user_id', $user_id)->first(); - public function getKYC($id) - { - $user = User::with(['shuftipro', 'profile'])->where('id', $id)->first(); - if (!$user || $user->role == 'admin') { - return $this->errorResponse(__('api.error.not_found'), Response::HTTP_NOT_FOUND); + if (!$shuftipro) { + $shuftipro = new Shuftipro; + $shuftipro->user_id = $user_id; + $shuftipro->reference_id = 'ByPass#' . time(); + } + + $shuftipro->is_successful = 1; + $shuftipro->status = 'approved'; + $shuftipro->manual_approved_at = $now; + $shuftipro->manual_reviewer = $admin_user->email; + $shuftipro->save(); } - $response = $user->load(['profile', 'shuftipro']); - return $this->successResponse($response); + + return $this->metaSuccess(); } // get intake @@ -227,8 +987,16 @@ public function getIntakes(Request $request) $limit = $request->limit ?? 50; $search = $request->search ?? ''; $users = User::select([ - 'id', 'email', 'node_verified_at', 'letter_verified_at', 'signature_request_id', 'created_at', - 'first_name', 'last_name', 'letter_file', 'letter_rejected_at' + 'id', + 'email', + 'node_verified_at', + 'letter_verified_at', + 'signature_request_id', + 'created_at', + 'first_name', + 'last_name', + 'letter_file', + 'letter_rejected_at' ]) ->where('banned', 0) ->where('role', 'member') @@ -238,7 +1006,9 @@ public function getIntakes(Request $request) ->orWhere('users.signature_request_id', null); }) ->where(function ($query) use ($search) { - if ($search) $query->where('users.email', 'like', '%' . $search . '%'); + if ($search) { + $query->where('users.email', 'like', '%' . $search . '%'); + } }) ->orderBy('users.id', 'desc') ->paginate($limit); @@ -253,97 +1023,106 @@ public function submitBallot(Request $request) $user = auth()->user(); // Validator $validator = Validator::make($request->all(), [ - 'title' => 'required', + 'title' => 'required', 'description' => 'required', - // 'time' => 'required', - // 'time_unit' => 'required|in:minutes,hours,days', - 'files' => 'array', - 'files.*' => 'file|max:10240|mimes:pdf,docx,doc,txt,rtf', - 'start_date' => 'required', - 'start_time' => 'required', - 'end_date' => 'required', - 'end_time' => 'required', + 'files' => 'array', + // 'files.*' => 'file|max:10240|mimes:pdf,docx,doc,txt,rtf', + 'files.*' => 'file|max:2048|mimes:pdf,docx,doc,txt,rtf', + 'start_date' => 'required', + 'start_time' => 'required', + 'end_date' => 'required', + 'end_time' => 'required', + 'timezone' => 'required' ]); + if ($validator->fails()) { return $this->validateResponse($validator->errors()); } - $time = $request->time; - $timeUnit = $request->time_unit; - $mins = 0; - if ($timeUnit == 'minutes') { - $mins = $time; - } else if ($timeUnit == 'hours') { - $mins = $time * 60; - } else if ($timeUnit == 'days') { - $mins = $time * 60 * 24; - } - $start = Carbon::createFromFormat("Y-m-d H:i:s", Carbon::now('UTC'), "UTC"); - $now = Carbon::now('UTC'); - $timeEnd = $start->addMinutes($mins); + $timezone = $request->timezone; + $startTime = $request->start_date . ' ' . $request->start_time; + $startTimeCarbon = Carbon::createFromFormat('Y-m-d H:i:s', $startTime, $timezone); + $startTimeCarbon->setTimezone('UTC'); + $endTime = $request->end_date . ' ' . $request->end_time; - $endTimeCarbon = Carbon::createFromFormat('Y-m-d H:i:s', $endTime, 'EST'); + $endTimeCarbon = Carbon::createFromFormat('Y-m-d H:i:s', $endTime, $timezone); $endTimeCarbon->setTimezone('UTC'); + if ($startTimeCarbon->gte($endTimeCarbon)) { + return $this->errorResponse('End datetime must greater than start datetime', Response::HTTP_BAD_REQUEST); + } + $ballot = new Ballot(); - $ballot->user_id = $user->id; - $ballot->title = $request->title; + $ballot->user_id = $user->id; + $ballot->title = $request->title; $ballot->description = $request->description; - // $ballot->time = $time; - // $ballot->time_unit = $timeUnit; - // $ballot->time_end = $timeEnd; - $ballot->time_end = $endTimeCarbon; - $ballot->start_date = $request->start_date; - $ballot->start_time = $request->start_time; - $ballot->end_date = $request->end_date; - $ballot->end_time = $request->end_time; - $ballot->status = 'active'; - $ballot->created_at = $now; + $ballot->time_begin = $startTimeCarbon; + $ballot->time_end = $endTimeCarbon; + $ballot->start_date = $request->start_date; + $ballot->start_time = $request->start_time; + $ballot->end_date = $request->end_date; + $ballot->end_time = $request->end_time; + $ballot->status = 'active'; + $ballot->timezone = $timezone; $ballot->save(); + $vote = new Vote(); $vote->ballot_id = $ballot->id; $vote->save(); + if ($request->hasFile('files')) { $files = $request->file('files'); + foreach ($files as $file) { - $name = $file->getClientOriginalName(); - $extension = $file->getClientOriginalExtension(); - $filenamehash = md5(Str::random(10) . '_' . (string)time()); + $name = $file->getClientOriginalName(); + $extension = $file->getClientOriginalExtension(); + $filenamehash = md5(Str::random(10) . '_' . (string)time()); $fileNameToStore = $filenamehash . '.' . $extension; // S3 file upload $S3 = new S3Client([ - 'version' => 'latest', - 'region' => getenv('AWS_DEFAULT_REGION'), + 'version' => 'latest', + 'region' => getenv('AWS_DEFAULT_REGION'), 'credentials' => [ - 'key' => getenv('AWS_ACCESS_KEY_ID'), - 'secret' => getenv('AWS_SECRET_ACCESS_KEY'), + 'key' => getenv('AWS_ACCESS_KEY_ID'), + 'secret' => getenv('AWS_SECRET_ACCESS_KEY'), ], ]); $s3result = $S3->putObject([ - 'Bucket' => getenv('AWS_BUCKET'), - 'Key' => 'perks/' . $fileNameToStore, + 'Bucket' => getenv('AWS_BUCKET'), + 'Key' => 'perks/' . $fileNameToStore, 'SourceFile' => $file ]); - // $ObjectURL = 'https://'.getenv('AWS_BUCKET') . '.s3.amazonaws.com/perks/'.$fileNameToStore; - $ObjectURL = $s3result['ObjectURL'] ?? getenv('SITE_URL') . '/not-found'; - $ballotFile = new BallotFile(); + $ObjectURL = ( + $s3result['ObjectURL'] ?? + getenv('SITE_URL') . '/not-found') + ; + + $ballotFile = new BallotFile(); $ballotFile->ballot_id = $ballot->id; - $ballotFile->name = $name; - $ballotFile->path = $ObjectURL; - $ballotFile->url = $ObjectURL; + $ballotFile->name = $name; + $ballotFile->path = $ObjectURL; + $ballotFile->url = $ObjectURL; $ballotFile->save(); } } DB::commit(); + + BallotNotification::dispatch($ballot)->onQueue('default_long'); + return $this->metaSuccess(); } catch (\Exception $ex) { DB::rollBack(); - return $this->errorResponse('Submit ballot fail', Response::HTTP_BAD_REQUEST, $ex->getMessage()); + + return $this->errorResponse( + 'Submit ballot fail', + Response::HTTP_BAD_REQUEST, + $ex->getMessage() + ); } } @@ -353,171 +1132,181 @@ public function editBallot($id, Request $request) DB::beginTransaction(); // Validator $validator = Validator::make($request->all(), [ - 'title' => 'nullable', - 'description' => 'nullable', - // 'time' => 'nullable', - // 'time_unit' => 'nullable|in:minutes,hours,days', - 'files' => 'array', - 'files.*' => 'file|max:10240|mimes:pdf,docx,doc,txt,rtf', + 'title' => 'nullable', + 'description' => 'nullable', + 'files' => 'array', + // 'files.*' => 'file|max:10240|mimes:pdf,docx,doc,txt,rtf', + 'files.*' => 'file|max:2048|mimes:pdf,docx,doc,txt,rtf', 'file_ids_remove' => 'array', - 'start_date' => 'required', - 'start_time' => 'required', - 'end_date' => 'required', - 'end_time' => 'required', + 'start_date' => 'required', + 'start_time' => 'required', + 'end_date' => 'required', + 'end_time' => 'required', + 'timezone' => 'required' ]); + if ($validator->fails()) { return $this->validateResponse($validator->errors()); } - $time = $request->time; - $timeUnit = $request->time_unit; + $ballot = Ballot::where('id', $id)->first(); if (!$ballot) { return $this->errorResponse('Not found ballot', Response::HTTP_BAD_REQUEST); } - if ($request->title) $ballot->title = $request->title; - if ($request->description) $ballot->description = $request->description; - $now = Carbon::now('UTC'); - $ballot->created_at = $now; - $ballot->time_end = $request->end_date . ' ' . $request->end_time; - $ballot->start_date = $request->start_date; - $ballot->start_time = $request->start_time; - $ballot->end_date = $request->end_date; - $ballot->end_time = $request->end_time; + $timezone = $request->timezone; + + if ($request->title) { + $ballot->title = $request->title; + } + + if ($request->description) { + $ballot->description = $request->description; + } + + $startTime = $request->start_date . ' ' . $request->start_time; + $startTimeCarbon = Carbon::createFromFormat('Y-m-d H:i:s', $startTime, $timezone); + $startTimeCarbon->setTimezone('UTC'); + + $endTime = $request->end_date . ' ' . $request->end_time; + $endTimeCarbon = Carbon::createFromFormat('Y-m-d H:i:s', $endTime, $timezone); + $endTimeCarbon->setTimezone('UTC'); - /* - if($time && $timeUnit && ($time != $ballot->time || $timeUnit != $ballot->time_unit)) { - $mins = 0; - if ($timeUnit == 'minutes') { - $mins = $time; - } else if ($timeUnit == 'hours') { - $mins = $time * 60; - } else if ($timeUnit == 'days') { - $mins = $time * 60 * 24; - } - $start = Carbon::createFromFormat("Y-m-d H:i:s", Carbon::now('UTC'), "UTC"); - $now = Carbon::now('UTC'); - $timeEnd = $start->addMinutes($mins); - $ballot->time = $time; - $ballot->time_unit = $timeUnit; - $ballot->created_at = $now; - $ballot->time_end = $timeEnd; + if ($startTimeCarbon->gte($endTimeCarbon)) { + return $this->errorResponse('End datetime must greater than start datetime', Response::HTTP_BAD_REQUEST); } - */ + $ballot->time_begin = $startTimeCarbon; + $ballot->time_end = $endTimeCarbon; + $ballot->start_date = $request->start_date; + $ballot->start_time = $request->start_time; + $ballot->end_date = $request->end_date; + $ballot->end_time = $request->end_time; + $ballot->timezone = $request->timezone; $ballot->save(); + if ($request->hasFile('files')) { $files = $request->file('files'); + foreach ($files as $file) { - $name = $file->getClientOriginalName(); - $extension = $file->getClientOriginalExtension(); - $filenamehash = md5(Str::random(10) . '_' . (string)time()); + $name = $file->getClientOriginalName(); + $extension = $file->getClientOriginalExtension(); + $filenamehash = md5(Str::random(10) . '_' . (string)time()); $fileNameToStore = $filenamehash . '.' . $extension; // S3 file upload $S3 = new S3Client([ - 'version' => 'latest', - 'region' => getenv('AWS_DEFAULT_REGION'), + 'version' => 'latest', + 'region' => getenv('AWS_DEFAULT_REGION'), 'credentials' => [ - 'key' => getenv('AWS_ACCESS_KEY_ID'), - 'secret' => getenv('AWS_SECRET_ACCESS_KEY'), + 'key' => getenv('AWS_ACCESS_KEY_ID'), + 'secret' => getenv('AWS_SECRET_ACCESS_KEY'), ], ]); $s3result = $S3->putObject([ - 'Bucket' => getenv('AWS_BUCKET'), - 'Key' => 'perks/'.$fileNameToStore, + 'Bucket' => getenv('AWS_BUCKET'), + 'Key' => 'perks/'.$fileNameToStore, 'SourceFile' => $file ]); - // $ObjectURL = 'https://'.getenv('AWS_BUCKET').'.s3.amazonaws.com/perks/'.$fileNameToStore; - $ObjectURL = $s3result['ObjectURL'] ?? getenv('SITE_URL').'/not-found'; - $ballotFile = new BallotFile(); + $ObjectURL = ( + $s3result['ObjectURL'] ?? + getenv('SITE_URL').'/not-found' + ); + + $ballotFile = new BallotFile(); $ballotFile->ballot_id = $ballot->id; - $ballotFile->name = $name; - $ballotFile->path = $ObjectURL; - $ballotFile->url = $ObjectURL; + $ballotFile->name = $name; + $ballotFile->path = $ObjectURL; + $ballotFile->url = $ObjectURL; $ballotFile->save(); } } + if ($request->file_ids_remove) { foreach($request->file_ids_remove as $file_id) { - BallotFile::where('id', $file_id)->where('ballot_id', $id)->delete(); + BallotFile::where('id', $file_id) + ->where('ballot_id', $id) + ->delete(); } } DB::commit(); + return $this->metaSuccess(); } catch (\Exception $ex) { DB::rollBack(); - return $this->errorResponse('Submit ballot fail', Response::HTTP_BAD_REQUEST, $ex->getMessage()); + + return $this->errorResponse( + 'Submit ballot fail', + Response::HTTP_BAD_REQUEST, + $ex->getMessage() + ); } } public function getBallots(Request $request) { - $limit = $request->limit ?? 50; - $status = $request->status; - $sort_key = $request->sort_key ?? ''; - $sort_direction = $request->sort_direction ?? ''; - if (!$sort_key) $sort_key = 'ballot.id'; - if (!$sort_direction) $sort_direction = 'desc'; - - $now = Carbon::now('EST'); - $startDate = $now->format('Y-m-d'); - $startTime = $now->format('H:i:s'); + $limit = $request->limit ?? 50; + $status = $request->status; + $sort_key = $request->sort_key ?? 'ballot.id'; + $sort_direction = $request->sort_direction ?? 'desc'; + $now = Carbon::now('UTC'); - if ($status == 'active') { + if ($status == 'active') { $ballots = Ballot::with(['user', 'vote']) - ->where('ballot.status', 'active') - ->where(function ($query) use ($startDate, $startTime) { - $query->where('start_date', '<', $startDate) - ->orWhere(function ($query) use ($startDate, $startTime) { - $query->where('start_date', $startDate) - ->where('start_time', '<=', $startTime); - }); - }) - ->orderBy($sort_key, $sort_direction) - ->paginate($limit); + ->where('ballot.status', 'active') + ->where('ballot.time_begin', '<=', $now) + ->orderBy($sort_key, $sort_direction) + ->paginate($limit); } else if ($status && $status == 'scheduled') { $ballots = Ballot::with(['user', 'vote']) - ->where('ballot.status', 'active') - ->where(function ($query) use ($startDate, $startTime) { - $query->where('start_date', '>', $startDate) - ->orWhere(function ($query) use ($startDate, $startTime) { - $query->where('start_date', $startDate) - ->where('start_time', '>', $startTime); - }); - }) - ->orderBy($sort_key, $sort_direction) - ->paginate($limit); + ->where('ballot.status', 'active') + ->where('ballot.time_begin', '>', $now) + ->orderBy($sort_key, $sort_direction) + ->paginate($limit); } else if ($status && $status != 'active' && $status != 'scheduled') { $ballots = Ballot::with(['user', 'vote']) - ->where('ballot.status', '!=', 'active') - ->orderBy($sort_key, $sort_direction) - ->paginate($limit); + ->where('ballot.status', '!=', 'active') + ->orderBy($sort_key, $sort_direction) + ->paginate($limit); } else { - $ballots = Ballot::with(['user', 'vote'])->orderBy($sort_key, $sort_direction)->paginate($limit); + $ballots = Ballot::with(['user', 'vote']) + ->orderBy($sort_key, $sort_direction) + ->paginate($limit); } return $this->successResponse($ballots); } public function getDetailBallot($id) { - $ballot = Ballot::with(['user', 'vote', 'files'])->where('id', $id)->first(); + $ballot = Ballot::with(['user', 'vote', 'files']) + ->where('id', $id) + ->first(); + if (!$ballot) { - return $this->errorResponse('Not found ballot', Response::HTTP_BAD_REQUEST); + return $this->errorResponse( + 'Not found ballot', + Response::HTTP_BAD_REQUEST + ); } + return $this->successResponse($ballot); } public function cancelBallot($id) { $ballot = Ballot::where('id', $id)->first(); + if (!$ballot || $ballot->status != 'active') { - return $this->errorResponse('Cannot cancle ballot', Response::HTTP_BAD_REQUEST); + return $this->errorResponse( + 'Cannot cancel ballot', + Response::HTTP_BAD_REQUEST + ); } - $ballot->time_end = now(); - $ballot->status = 'cancelled'; + + $ballot->time_end = Carbon::now('UTC'); + $ballot->status = 'cancelled'; $ballot->save(); return $this->metaSuccess(); } @@ -525,7 +1314,10 @@ public function cancelBallot($id) public function getBallotVotes($id, Request $request) { $limit = $request->limit ?? 50; - $data = VoteResult::where('ballot_id', '=', $id)->with(['user', 'user.profile'])->orderBy('created_at', 'ASC')->paginate($limit); + $data = VoteResult::where('ballot_id', '=', $id) + ->with(['user', 'user.profile']) + ->orderBy('created_at', 'ASC') + ->paginate($limit); return $this->successResponse($data); } @@ -533,45 +1325,76 @@ public function getBallotVotes($id, Request $request) public function getViewFileBallot(Request $request, $fileId) { $limit = $request->limit ?? 50; - $data = BallotFileView::where('ballot_file_id', '=', $fileId)->with(['user', 'user.profile'])->orderBy('created_at', 'ASC')->paginate($limit); + $data = BallotFileView::where('ballot_file_id', '=', $fileId) + ->with(['user', 'user.profile']) + ->orderBy('created_at', 'ASC') + ->paginate($limit); + return $this->successResponse($data); } // Get Global Settings public function getGlobalSettings() { - $items = Setting::get(); - $settings = []; - if ($items) { - foreach ($items as $item) { - $settings[$item->name] = $item->value; - } - } + $settings = Helper::getSettings(); + + $ruleKycNotVerify = LockRules::where('type', 'kyc_not_verify') + ->orderBy('id', 'ASC') + ->select(['id', 'screen', 'is_lock']) + ->get(); + $ruleStatusIsPoor = LockRules::where('type', 'status_is_poor') + ->orderBy('id', 'ASC') + ->select(['id', 'screen', 'is_lock']) + ->get(); + + $membershipAgreementFile = MembershipAgreementFile::first(); + + $contactRecipients = ContactRecipient::orderBy('created_at', 'desc')->get(); - return $this->successResponse($settings); + $data = [ + 'globalSettings' => $settings, + 'lockRules' => [ + 'kyc_not_verify' => $ruleKycNotVerify, + 'status_is_poor' => $ruleStatusIsPoor + ], + 'membershipAgreementFile' => $membershipAgreementFile, + 'contactRecipients' => $contactRecipients + ]; + + return $this->successResponse($data); } // Update Global Settings public function updateGlobalSettings(Request $request) { - $validator = Validator::make($request->all(), [ - 'quorum_rate_ballot' => 'required', - ]); - if ($validator->fails()) { - return $this->validateResponse($validator->errors()); - } $items = [ - 'quorum_rate_ballot' => $request->quorum_rate_ballot, + 'quorum_rate_ballot' => ($request->quorum_rate_ballot ?? null), + 'uptime_warning' => ($request->uptime_warning ?? null), + 'uptime_probation' => ($request->uptime_probation ?? null), + 'uptime_correction_unit' => ($request->uptime_correction_unit ?? null), + 'uptime_correction_value' => ($request->uptime_correction_value ?? null), + 'uptime_calc_size' => ($request->uptime_calc_size ?? null), + 'voting_eras_to_vote' => ($request->voting_eras_to_vote ?? null), + 'voting_eras_since_redmark' => ($request->voting_eras_since_redmark ?? null), + 'redmarks_revoke' => ($request->redmarks_revoke ?? null), + 'redmarks_revoke_calc_size' => ($request->redmarks_revoke_calc_size ?? null), + 'responsiveness_warning' => ($request->responsiveness_warning ?? null), + 'responsiveness_probation' => ($request->responsiveness_probation ?? null) ]; + foreach ($items as $name => $value) { - $setting = Setting::where('name', $name)->first(); - if ($setting) { - $setting->value = $value; - $setting->save(); - } else { - $setting = new Setting(); - $setting->value = $value; - $setting->save(); + if ($value !== null) { + $setting = Setting::where('name', $name)->first(); + + if ($setting) { + $setting->value = $value; + $setting->save(); + } else { + $setting = new Setting(); + $setting->name = $name; + $setting->value = $value; + $setting->save(); + } } } @@ -580,57 +1403,72 @@ public function updateGlobalSettings(Request $request) public function getSubAdmins(Request $request) { - $limit = $request->limit ?? 50; - $admins = User::with(['permissions'])->where(['role' => 'sub-admin']) + $limit = $request->limit ?? 50; + $admins = User::with(['permissions']) + ->where(['role' => 'sub-admin']) ->orderBy('created_at', 'DESC') ->paginate($limit); return $this->successResponse($admins); } - + public function inviteSubAdmin(Request $request) { $validator = Validator::make($request->all(), [ 'email' => 'required|email', ]); + if ($validator->fails()) { return $this->validateResponse($validator->errors()); } $isExist = User::where(['email' => $request->email])->count() > 0; + if ($isExist) { - return $this->errorResponse('This email has already been used to invite another admin.', Response::HTTP_BAD_REQUEST); + return $this->errorResponse( + 'This email has already been used to invite another admin.', + Response::HTTP_BAD_REQUEST + ); } - $code = Str::random(6); - // $url = $request->header('origin') ?? $request->root(); - $url = getenv('SITE_URL'); - $inviteUrl = $url . '/register-sub-admin?code=' . $code . '&email=' . urlencode($request->email); - - VerifyUser::where('email', $request->email)->where('type', VerifyUser::TYPE_INVITE_ADMIN)->delete(); - - $verify = new VerifyUser(); - $verify->email = $request->email; - $verify->type = VerifyUser::TYPE_INVITE_ADMIN; - $verify->code = $code; - $verify->created_at = now(); + $code = Str::random(6); + $url = getenv('SITE_URL'); + + $inviteUrl = ( + $url . + '/register-sub-admin?code=' . + $code . + '&email=' . + urlencode($request->email) + ); + + VerifyUser::where('email', $request->email) + ->where('type', VerifyUser::TYPE_INVITE_ADMIN) + ->delete(); + + $verify = new VerifyUser(); + $verify->email = $request->email; + $verify->type = VerifyUser::TYPE_INVITE_ADMIN; + $verify->code = $code; + $verify->created_at = Carbon::now('UTC'); $verify->save(); + $admin = User::create([ - 'first_name' => 'faker', - 'last_name' => 'faker', - 'email' => $request->email, - 'password' => '', - 'type' => '', + 'first_name' => 'faker', + 'last_name' => 'faker', + 'email' => $request->email, + 'password' => '', + 'type' => '', 'member_status' => 'invited', - 'role' => 'sub-admin' + 'role' => 'sub-admin' ]); $data = [ - ['name' => 'intake', 'is_permission' => 0, 'user_id' => $admin->id], - ['name' => 'users', 'is_permission' => 0, 'user_id' => $admin->id], + ['name' => 'intake', 'is_permission' => 0, 'user_id' => $admin->id], + ['name' => 'users', 'is_permission' => 0, 'user_id' => $admin->id], ['name' => 'ballots', 'is_permission' => 0, 'user_id' => $admin->id], - ['name' => 'perks', 'is_permission' => 0, 'user_id' => $admin->id], - ['name' => 'teams', 'is_permission' => 0, 'user_id' => $admin->id], + ['name' => 'perks', 'is_permission' => 0, 'user_id' => $admin->id], + ['name' => 'teams', 'is_permission' => 0, 'user_id' => $admin->id], ]; Permission::insert($data); @@ -641,30 +1479,63 @@ public function inviteSubAdmin(Request $request) public function changeSubAdminPermissions(Request $request, $id) { - $validator = Validator::make($request->all(), [ - 'intake' => 'nullable|in:0,1', - 'users' => 'nullable|in:0,1', + $validator = Validator::make($request->all(), [ + 'intake' => 'nullable|in:0,1', + 'users' => 'nullable|in:0,1', 'ballots' => 'nullable|in:0,1', - 'perks' => 'nullable|in:0,1', - 'teams' => 'nullable|in:0,1', + 'perks' => 'nullable|in:0,1', + 'teams' => 'nullable|in:0,1', ]); if ($validator->fails()) { return $this->validateResponse($validator->errors()); } + $admin = User::find($id); - if ($admin == null || $admin->role != 'sub-admin') { - return $this->errorResponse('There is no admin user with this email', Response::HTTP_BAD_REQUEST); + + if ( + $admin == null || + $admin->role != 'sub-admin' + ) { + return $this->errorResponse( + 'There is no admin user with this email', + Response::HTTP_BAD_REQUEST + ); + } + + if (isset($request->globalsettings)) { + $permisstion = Permission::where('user_id', $id) + ->where('name', 'globalsettings') + ->first(); + + if ($permisstion) { + $permisstion->is_permission = $request->globalsettings; + $permisstion->save(); + } else { + $permisstion = new Permission(); + $permisstion->is_permission = $request->globalsettings; + $permisstion->user_id = $id; + $permisstion->name = 'globalsettings'; + $permisstion->save(); + } } + if (isset($request->intake)) { - $permisstion = Permission::where('user_id', $id)->where('name', 'intake')->first(); + $permisstion = Permission::where('user_id', $id) + ->where('name', 'intake') + ->first(); + if ($permisstion) { $permisstion->is_permission = $request->intake; $permisstion->save(); } } + if (isset($request->users)) { - $permisstion = Permission::where('user_id', $id)->where('name', 'users')->first(); + $permisstion = Permission::where('user_id', $id) + ->where('name', 'users') + ->first(); + if ($permisstion) { $permisstion->is_permission = $request->users; $permisstion->save(); @@ -672,7 +1543,10 @@ public function changeSubAdminPermissions(Request $request, $id) } if (isset($request->ballots)) { - $permisstion = Permission::where('user_id', $id)->where('name', 'ballots')->first(); + $permisstion = Permission::where('user_id', $id) + ->where('name', 'ballots') + ->first(); + if ($permisstion) { $permisstion->is_permission = $request->ballots; $permisstion->save(); @@ -680,7 +1554,10 @@ public function changeSubAdminPermissions(Request $request, $id) } if (isset($request->perks)) { - $permisstion = Permission::where('user_id', $id)->where('name', 'perks')->first(); + $permisstion = Permission::where('user_id', $id) + ->where('name', 'perks') + ->first(); + if ($permisstion) { $permisstion->is_permission = $request->perks; $permisstion->save(); @@ -688,15 +1565,18 @@ public function changeSubAdminPermissions(Request $request, $id) } if (isset($request->teams)) { - $permisstion = Permission::where('user_id', $id)->where('name', 'teams')->first(); + $permisstion = Permission::where('user_id', $id) + ->where('name', 'teams') + ->first(); + if ($permisstion) { $permisstion->is_permission = $request->teams; $permisstion->save(); } else { - $permisstion = new Permission(); + $permisstion = new Permission(); $permisstion->is_permission = $request->teams; - $permisstion->user_id = $id; - $permisstion->name = 'teams'; + $permisstion->user_id = $id; + $permisstion->name = 'teams'; $permisstion->save(); } } @@ -707,21 +1587,37 @@ public function changeSubAdminPermissions(Request $request, $id) public function resendLink(Request $request, $id) { $admin = User::find($id); - if ($admin == null || $admin->role != 'sub-admin') - return $this->errorResponse('No admin to be send invite link', Response::HTTP_BAD_REQUEST); - $code = Str::random(6); - // $url = $request->header('origin') ?? $request->root(); - $url = getenv('SITE_URL'); - $inviteUrl = $url . '/register-sub-admin?code=' . $code . '&email=' . urlencode($admin->email); - - VerifyUser::where('email', $admin->email)->where('type', VerifyUser::TYPE_INVITE_ADMIN)->delete(); - - $verify = new VerifyUser(); - $verify->email = $admin->email; - $verify->type = VerifyUser::TYPE_INVITE_ADMIN; - $verify->code = $code; - $verify->created_at = now(); + if ( + $admin == null || + $admin->role != 'sub-admin' + ) { + return $this->errorResponse( + 'No admin to be send invite link', + Response::HTTP_BAD_REQUEST + ); + } + + $code = Str::random(6); + $url = getenv('SITE_URL'); + + $inviteUrl = ( + $url . + '/register-sub-admin?code=' . + $code . + '&email=' . + urlencode($admin->email) + ); + + VerifyUser::where('email', $admin->email) + ->where('type', VerifyUser::TYPE_INVITE_ADMIN) + ->delete(); + + $verify = new VerifyUser(); + $verify->email = $admin->email; + $verify->type = VerifyUser::TYPE_INVITE_ADMIN; + $verify->code = $code; + $verify->created_at = Carbon::now('UTC'); $verify->save(); Mail::to($admin->email)->send(new InvitationMail($inviteUrl)); @@ -732,21 +1628,36 @@ public function resendLink(Request $request, $id) public function resetSubAdminResetPassword(Request $request, $id) { $admin = User::find($id); - if ($admin == null || $admin->role != 'sub-admin') - return $this->errorResponse('No admin to be revoked', Response::HTTP_BAD_REQUEST); - $code = Str::random(6); - // $url = $request->header('origin') ?? $request->root(); - $url = getenv('SITE_URL'); - $resetUrl = $url . '/update-password?code=' . $code . '&email=' . urlencode($admin->email); - - VerifyUser::where('email', $admin->email)->where('type', VerifyUser::TYPE_RESET_PASSWORD)->delete(); - - $verify = new VerifyUser(); - $verify->email = $admin->email; - $verify->type = VerifyUser::TYPE_RESET_PASSWORD; - $verify->code = $code; - $verify->created_at = now(); + if ( + $admin == null || + $admin->role != 'sub-admin' + ) { + return $this->errorResponse( + 'No admin to be revoked', + Response::HTTP_BAD_REQUEST + ); + } + + $code = Str::random(6); + $url = getenv('SITE_URL'); + $resetUrl = ( + $url . + '/update-password?code=' . + $code . + '&email=' . + urlencode($admin->email) + ); + + VerifyUser::where('email', $admin->email) + ->where('type', VerifyUser::TYPE_RESET_PASSWORD) + ->delete(); + + $verify = new VerifyUser(); + $verify->email = $admin->email; + $verify->type = VerifyUser::TYPE_RESET_PASSWORD; + $verify->code = $code; + $verify->created_at = Carbon::now('UTC'); $verify->save(); Mail::to($admin->email)->send(new ResetPasswordMail($resetUrl)); @@ -757,11 +1668,19 @@ public function resetSubAdminResetPassword(Request $request, $id) public function revokeSubAdmin(Request $request, $id) { $admin = User::find($id); - if ($admin == null || $admin->role != 'sub-admin') - return $this->errorResponse('No admin to be revoked', Response::HTTP_BAD_REQUEST); + + if ( + $admin == null || + $admin->role != 'sub-admin' + ) { + return $this->errorResponse( + 'No admin to be revoked', + Response::HTTP_BAD_REQUEST + ); + } $admin->member_status = 'revoked'; - $admin->banned = 1; + $admin->banned = 1; $admin->save(); return $this->metaSuccess(); @@ -770,13 +1689,23 @@ public function revokeSubAdmin(Request $request, $id) public function undoRevokeSubAdmin(Request $request, $id) { $admin = User::find($id); - if ($admin == null || $admin->role != 'sub-admin') - return $this->errorResponse('No admin to be revoked', Response::HTTP_BAD_REQUEST); + + if ( + $admin == null || + $admin->role != 'sub-admin' + ) { + return $this->errorResponse( + 'No admin to be revoked', + Response::HTTP_BAD_REQUEST + ); + } + if ($admin->password) { $admin->member_status = 'active'; } else { $admin->member_status = 'invited'; } + $admin->banned = 0; $admin->save(); @@ -786,72 +1715,126 @@ public function undoRevokeSubAdmin(Request $request, $id) public function getIpHistories(Request $request, $id) { $admin = User::find($id); - if ($admin == null || $admin->role != 'sub-admin') { - return $this->errorResponse('Not found admin', Response::HTTP_BAD_REQUEST); + + if ( + $admin == null || + $admin->role != 'sub-admin' + ) { + return $this->errorResponse( + 'Not found admin', + Response::HTTP_BAD_REQUEST + ); } - $limit = $request->limit ?? 50; + + $limit = $request->limit ?? 50; $ipAddress = IpHistory::where(['user_id' => $admin->id]) ->orderBy('created_at', 'DESC') ->paginate($limit); return $this->successResponse($ipAddress); } - + public function approveIntakeUser($id) { $admin = auth()->user(); + $user = User::where('id', $id) + ->where('banned', 0) + ->where('role', 'member') + ->first(); - $user = User::where('id', $id)->where('banned', 0)->where('role', 'member')->first(); if ($user && $user->letter_file) { - $user->letter_verified_at = now(); + $user->letter_verified_at = Carbon::now('UTC'); $user->save(); $emailerData = EmailerHelper::getEmailerData(); - EmailerHelper::triggerUserEmail($user->email, 'Your letter of motivation is APPROVED', $emailerData, $user); - if ($user->letter_verified_at && $user->node_verified_at) { - EmailerHelper::triggerUserEmail($user->email, 'Congratulations', $emailerData, $user); + + EmailerHelper::triggerUserEmail( + $user->email, + 'Your letter of motivation is APPROVED', + $emailerData, + $user + ); + + if ( + $user->letter_verified_at && + $user->node_verified_at + ) { + EmailerHelper::triggerUserEmail( + $user->email, + 'Congratulations', + $emailerData, + $user + ); } return $this->metaSuccess(); } - return $this->errorResponse('Fail approved User', Response::HTTP_BAD_REQUEST); + + return $this->errorResponse( + 'Fail approved User', + Response::HTTP_BAD_REQUEST + ); } public function resetIntakeUser($id, Request $request) { $admin = auth()->user(); + $user = User::where('id', $id) + ->where('banned', 0) + ->where('role', 'member') + ->first(); - $user = User::where('id', $id)->where('banned', 0)->where('role', 'member')->first(); if ($user) { $user->letter_verified_at = null; - $user->letter_file = null; - $user->letter_rejected_at = now(); + $user->letter_file = null; + $user->letter_rejected_at = Carbon::now('UTC'); $user->save(); $message = trim($request->get('message')); + if (!$message) { - return $this->errorResponse('please input message', Response::HTTP_BAD_REQUEST); + return $this->errorResponse( + 'please input message', + Response::HTTP_BAD_REQUEST + ); } - Mail::to($user->email)->send(new AdminAlert('You need to submit letter again', $message)); + + Mail::to($user->email)->send(new AdminAlert( + 'You need to submit letter again', + $message + )); + return $this->metaSuccess(); } - return $this->errorResponse('Fail reset User', Response::HTTP_BAD_REQUEST); + + return $this->errorResponse( + 'Fail reset User', + Response::HTTP_BAD_REQUEST + ); } public function banUser($id) { $admin = auth()->user(); + $user = User::where('id', $id) + ->where('banned', 0) + ->first(); - $user = User::where('id', $id)->where('banned', 0)->first(); if ($user) { $user->banned = 1; $user->save(); return $this->metaSuccess(); } - return $this->errorResponse('Fail Ban User', Response::HTTP_BAD_REQUEST); + return $this->errorResponse( + 'Fail Ban User', + Response::HTTP_BAD_REQUEST + ); } public function removeUser($id, Request $request) { - $user = User::where('id', $id)->where('role', 'member')->first(); + $user = User::where('id', $id) + ->where('role', 'member') + ->first(); + if ($user) { Shuftipro::where('user_id', $user->id)->delete(); ShuftiproTemp::where('user_id', $user->id)->delete(); @@ -859,27 +1842,29 @@ public function removeUser($id, Request $request) $user->delete(); return $this->metaSuccess(); } - return $this->errorResponse('Fail remove User', Response::HTTP_BAD_REQUEST); + return $this->errorResponse( + 'Fail remove User', + Response::HTTP_BAD_REQUEST + ); } public function getVerificationUsers(Request $request) { $limit = $request->limit ?? 50; - $users = User::where('users.role', 'member')->where('banned', 0) - ->join('profile', function ($query) { - $query->on('profile.user_id', '=', 'users.id') - ->where('profile.status', 'pending'); - }) - ->join('shuftipro', 'shuftipro.user_id', '=', 'users.id') - ->select([ - 'users.id as user_id', - 'users.created_at', - 'users.email', - 'profile.*', - 'shuftipro.status as kyc_status', - 'shuftipro.background_checks_result', - 'shuftipro.manual_approved_at' - ])->paginate($limit); + $users = User::where('users.role', 'member') + ->where('banned', 0) + ->join('shuftipro', 'shuftipro.user_id', '=', 'users.id') + ->where('shuftipro.status', 'denied') + ->orWhere('shuftipro.status', 'pending') + ->select([ + 'users.id as user_id', + 'users.created_at', + 'users.email', + 'shuftipro.status as kyc_status', + 'shuftipro.background_checks_result', + 'shuftipro.manual_approved_at' + ])->paginate($limit); + return $this->successResponse($users); } @@ -887,17 +1872,23 @@ public function getVerificationUsers(Request $request) public function resetKYC($id, Request $request) { $admin = auth()->user(); - $message = trim($request->get('message')); + if (!$message) { - return $this->errorResponse('please input message', Response::HTTP_BAD_REQUEST); + return $this->errorResponse( + 'please input message', + Response::HTTP_BAD_REQUEST + ); } - $user = User::with(['profile'])->where('id', $id)->first(); + $user = User::with(['profile']) + ->where('id', $id) + ->first(); + if ($user && $user->profile) { $user->profile->status = null; $user->profile->save(); - + Profile::where('user_id', $user->id)->delete(); Shuftipro::where('user_id', $user->id)->delete(); ShuftiproTemp::where('user_id', $user->id)->delete(); @@ -907,158 +1898,89 @@ public function resetKYC($id, Request $request) $user->approve_at = null; $user->reset_kyc = 1; $user->save(); - - Mail::to($user->email)->send(new AdminAlert('You need to submit KYC again', $message)); - return $this->metaSuccess(); - } - - return $this->errorResponse('Fail Reset KYC', Response::HTTP_BAD_REQUEST); - } - - public function refreshLinks($id) - { - $url = 'https://api.shuftipro.com/status'; - $user = User::with('shuftipro')->find($id); - - $shuftipro = $user->shuftipro; - if ($shuftipro) { - $client_id = config('services.shufti.client_id'); - $secret_key = config('services.shufti.client_secret'); - - $response = Http::withBasicAuth($client_id, $secret_key)->post($url, [ - 'reference' => $shuftipro->reference_id - ]); - - $data = $response->json(); - if (!$data || !is_array($data)) return; - - if (!isset($data['reference']) || !isset($data['event'])) { - return $this->successResponse([ - 'success' => false, - ]); - } - - $events = [ - 'verification.accepted', - 'verification.declined', - 'request.timeout' - ]; - - if (!in_array($data['event'], $events)) { - return $this->successResponse([ - 'success' => false, - ]); - } - - $proofs = isset($data['proofs']) ? $data['proofs'] : null; - - if ($proofs && isset($proofs['document']) && isset($proofs['document']['proof'])) { - $shuftipro->document_proof = $proofs['document']['proof']; - } - - // Address Proof - if ($proofs && isset($proofs['address']) && isset($proofs['address']['proof'])) { - $shuftipro->address_proof = $proofs['address']['proof']; - } - - $shuftipro->save(); - - return $this->successResponse([ - 'success' => true, - ]); - } - - return $this->successResponse([ - 'success' => false, - ]); - } - public function banAndDenyUser($id) - { - $user = User::with(['shuftipro', 'profile']) - ->where('id', $id) - ->where('users.role', 'member') - ->where('banned', 0) - ->first(); + Mail::to($user->email)->send(new AdminAlert( + 'You need to submit KYC again', + $message + )); - if ($user && $user->profileT) { - $user->profile->status = 'denied'; - $user->profile->save(); - $user->banned = 1; - $user->save(); return $this->metaSuccess(); } - return $this->errorResponse('Fail deny and ban user', Response::HTTP_BAD_REQUEST); + return $this->errorResponse( + 'Fail Reset KYC', + Response::HTTP_BAD_REQUEST + ); } public function getVerificationDetail($id) { $user = User::with(['shuftipro', 'profile', 'documentFiles']) - ->leftJoin('shuftipro', 'shuftipro.user_id', '=', 'users.id') - ->where('users.id', $id) - ->select([ - 'users.*', - 'shuftipro.status as kyc_status', - 'shuftipro.background_checks_result', - ]) - ->where('users.role', 'member') - ->where('banned', 0) - ->first(); + ->leftJoin('shuftipro', 'shuftipro.user_id', '=', 'users.id') + ->where('users.id', $id) + ->select([ + 'users.*', + 'shuftipro.status as kyc_status', + 'shuftipro.background_checks_result', + 'shuftipro.data' + ]) + ->where('users.role', 'member') + ->where('banned', 0) + ->first(); if ($user) { - if (isset($user->shuftipro) && isset($user->shuftipro->address_proof) && $user->shuftipro->address_proof) { + if ( + isset($user->shuftipro) && + isset($user->shuftipro->address_proof) && + $user->shuftipro->address_proof + ) { $url = Storage::disk('local')->url($user->shuftipro->address_proof); $user->shuftipro->address_proof_link = asset($url); } - return $this->successResponse($user); - } - return $this->errorResponse('Fail get verification user', Response::HTTP_BAD_REQUEST); - } + $declined_reason = ''; - public function approveDocument($id) - { - $user = User::with(['profile']) - ->where('id', $id) - ->where('users.role', 'member') - ->where('banned', 0) - ->first(); + try { + $declined_reason = json_decode(json_decode($user->data))->declined_reason; + } catch (\Exception $ex) {} - if ($user && $user->profile) { - $user->profile->document_verified_at = now(); - $user->profile->save(); - return $this->metaSuccess(); + $user->declined_reason = $declined_reason; + + return $this->successResponse($user); } - return $this->errorResponse('Fail approve document', Response::HTTP_BAD_REQUEST); + return $this->errorResponse( + 'Fail get verification user', + Response::HTTP_BAD_REQUEST + ); } - public function activeUser($id) + public function approveDocument($id) { $user = User::with(['profile']) - ->where('id', $id) - ->where('users.role', 'member') - ->where('banned', 0) - ->first(); - + ->where('id', $id) + ->where('users.role', 'member') + ->where('banned', 0) + ->first(); + if ($user && $user->profile) { - $user->profile->status = 'approved'; + $user->profile->document_verified_at = Carbon::now('UTC'); $user->profile->save(); - $user->approve_at = now(); - $user->save(); return $this->metaSuccess(); } - return $this->errorResponse('Fail active document', Response::HTTP_BAD_REQUEST); + return $this->errorResponse( + 'Fail approve document', + Response::HTTP_BAD_REQUEST + ); } // Add Emailer Admin public function addEmailerAdmin(Request $request) { - $user = Auth::user(); - + $user = Auth::user(); $email = $request->get('email'); + if (!$email) { return [ 'success' => false, @@ -1067,6 +1989,7 @@ public function addEmailerAdmin(Request $request) } $record = EmailerAdmin::where('email', $email)->first(); + if ($record) { return [ 'success' => false, @@ -1094,27 +2017,34 @@ public function getEmailerData(Request $request) { $user = Auth::user(); $data = []; + $admins = EmailerAdmin::where('id', '>', 0) + ->orderBy('email', 'asc') + ->get(); + + $triggerAdmin = EmailerTriggerAdmin::where('id', '>', 0) + ->orderBy('id', 'asc') + ->get(); - $admins = EmailerAdmin::where('id', '>', 0)->orderBy('email', 'asc')->get(); - $triggerAdmin = EmailerTriggerAdmin::where('id', '>', 0)->orderBy('id', 'asc')->get(); - $triggerUser = EmailerTriggerUser::where('id', '>', 0)->orderBy('id', 'asc')->get(); + $triggerUser = EmailerTriggerUser::where('id', '>', 0) + ->orderBy('id', 'asc') + ->get(); $data = [ 'admins' => $admins, 'triggerAdmin' => $triggerAdmin, - 'triggerUser' => $triggerUser, + 'triggerUser' => $triggerUser, ]; return [ 'success' => true, - 'data' => $data + 'data' => $data ]; } // Update Emailer Trigger Admin public function updateEmailerTriggerAdmin($recordId, Request $request) { - $user = Auth::user(); + $user = Auth::user(); $record = EmailerTriggerAdmin::find($recordId); if ($record) { @@ -1136,51 +2066,12 @@ public function updateEmailerTriggerUser($recordId, Request $request) if ($record) { $enabled = (int) $request->get('enabled'); $content = $request->get('content'); - $record->enabled = $enabled; - if ($content) $record->content = $content; - - $record->save(); - - return ['success' => true]; - } - - return ['success' => false]; - } - - public function getMonitoringCriteria(Request $request) - { - $data = MonitoringCriteria::get(); - return $this->successResponse($data); - } - - public function updateMonitoringCriteria($type, Request $request) - { - $record = MonitoringCriteria::where('type', $type)->first(); - - if ($record) { - $validator = Validator::make($request->all(), [ - 'warning_level' => 'required|integer', - 'probation_start' => 'required', - // 'frame_calculate_unit' => 'required|in:Weeks,Days,Hours', - // 'frame_calculate_value' => 'required|integer', - 'given_to_correct_unit' => 'required|in:Weeks,Days,Hours', - 'given_to_correct_value' => 'required|integer', - // 'system_check_unit' => 'required|in:Weeks,Days,Hours', - // 'system_check_value' => 'required|integer', - ]); - if ($validator->fails()) - return $this->validateResponse($validator->errors()); + if ($content) { + $record->content = $content; + } - $record->warning_level = $request->warning_level; - $record->probation_start = $request->probation_start; - // $record->frame_calculate_unit = $request->frame_calculate_unit; - // $record->frame_calculate_value = $request->frame_calculate_value; - $record->given_to_correct_unit = $request->given_to_correct_unit; - $record->given_to_correct_value = $request->given_to_correct_value; - // $record->system_check_unit = $request->system_check_unit; - // $record->system_check_value = $request->system_check_value; $record->save(); return ['success' => true]; @@ -1195,64 +2086,32 @@ public function updateLockRules(Request $request, $id) 'is_lock' => 'required|boolean' ]); - if ($validator->fails()) return $this->validateResponse($validator->errors()); + if ($validator->fails()) { + return $this->validateResponse($validator->errors()); + } $rule = LockRules::where('id', $id)->first(); - $rule->is_lock = $request->is_lock; $rule->save(); return ['success' => true]; } - public function getLockRules() - { - $ruleKycNotVerify = LockRules::where('type', 'kyc_not_verify') - ->orderBy('id', 'ASC')->select(['id', 'screen', 'is_lock'])->get(); - $ruleStatusIsPoor = LockRules::where('type', 'status_is_poor') - ->orderBy('id', 'ASC')->select(['id', 'screen', 'is_lock'])->get(); - $data = [ - 'kyc_not_verify' => $ruleKycNotVerify, - 'status_is_poor' => $ruleStatusIsPoor, - ]; - return $this->successResponse($data); - } - - public function getListNodes(Request $request) - { - $limit = $request->limit ?? 50; - $node_failing = $request->node_failing ?? ''; - - $nodes = UserAddress::select([ - 'user_addresses.user_id as user_id', - 'user_addresses.public_address_node as public_address_node', - 'user_addresses.is_fail_node as is_fail_node', - 'user_addresses.rank as rank', - ]) - ->join('users', 'users.id', '=', 'user_addresses.user_id') - ->where('users.banned', 0) - ->whereNotNull('user_addresses.public_address_node') - ->where(function ($query) use ($node_failing) { - if ($node_failing == 1) $query->where('user_addresses.is_fail_node', 1); - }) - ->orderBy('user_addresses.rank', 'asc') - ->paginate($limit); - - return $this->successResponse($nodes); - } - // Get GraphInfo public function getGraphInfo(Request $request) { $user = Auth::user(); - $graphDataDay = $graphDataWeek = $graphDataMonth = $graphDataYear = []; + $graphDataDay = $graphDataWeek = $graphDataMonth = $graphDataYear = []; $timeDay = Carbon::now('UTC')->subHours(24); $timeWeek = Carbon::now('UTC')->subDays(7); $timeMonth = Carbon::now('UTC')->subDays(30); $timeYear = Carbon::now('UTC')->subYear(); - $items = TokenPrice::orderBy('created_at', 'desc')->where('created_at', '>=', $timeDay)->get(); + $items = TokenPrice::orderBy('created_at', 'desc') + ->where('created_at', '>=', $timeDay) + ->get(); + if ($items && count($items)) { foreach ($items as $item) { $name = strtotime($item->created_at); @@ -1260,7 +2119,10 @@ public function getGraphInfo(Request $request) } } - $items = TokenPrice::orderBy('created_at', 'desc')->where('created_at', '>=', $timeWeek)->get(); + $items = TokenPrice::orderBy('created_at', 'desc') + ->where('created_at', '>=', $timeWeek) + ->get(); + if ($items && count($items)) { foreach ($items as $item) { $name = strtotime($item->created_at); @@ -1268,7 +2130,10 @@ public function getGraphInfo(Request $request) } } - $items = TokenPrice::orderBy('created_at', 'desc')->where('created_at', '>=', $timeMonth)->get(); + $items = TokenPrice::orderBy('created_at', 'desc') + ->where('created_at', '>=', $timeMonth) + ->get(); + if ($items && count($items)) { foreach ($items as $item) { $name = strtotime($item->created_at); @@ -1276,7 +2141,10 @@ public function getGraphInfo(Request $request) } } - $items = TokenPrice::orderBy('created_at', 'desc')->where('created_at', '>=', $timeYear)->get(); + $items = TokenPrice::orderBy('created_at', 'desc') + ->where('created_at', '>=', $timeYear) + ->get(); + if ($items && count($items)) { foreach ($items as $item) { $name = strtotime($item->created_at); @@ -1285,10 +2153,10 @@ public function getGraphInfo(Request $request) } return $this->successResponse([ - 'day' => $graphDataDay, - 'week' => $graphDataWeek, + 'day' => $graphDataDay, + 'week' => $graphDataWeek, 'month' => $graphDataMonth, - 'year' => $graphDataYear, + 'year' => $graphDataYear, ]); } @@ -1297,55 +2165,51 @@ public function uploadMembershipFile(Request $request) try { // Validator $validator = Validator::make($request->all(), [ - 'file' => 'required|mimes:pdf,docx,doc,txt,rtf|max:5000', + 'file' => 'required|mimes:pdf,docx,doc,txt,rtf|max:2048', ]); - if ($validator->fails()) + if ($validator->fails()) { return $this->validateResponse($validator->errors()); + } $filenameWithExt = $request->file('file')->getClientOriginalName(); - //Get just filename - $filename = pathinfo($filenameWithExt, PATHINFO_FILENAME); - // Get just ext - $extension = $request->file('file')->getClientOriginalExtension(); - // new filename hash - $filenamehash = md5(Str::random(10) . '_' . (string)time()); - // Filename to store + $filename = pathinfo($filenameWithExt, PATHINFO_FILENAME); + $extension = $request->file('file')->getClientOriginalExtension(); + $filenamehash = md5(Str::random(10) . '_' . (string)time()); $fileNameToStore = $filenamehash . '.' . $extension; // S3 File Upload $S3 = new S3Client([ - 'version' => 'latest', - 'region' => getenv('AWS_DEFAULT_REGION'), + 'version' => 'latest', + 'region' => getenv('AWS_DEFAULT_REGION'), 'credentials' => [ - 'key' => getenv('AWS_ACCESS_KEY_ID'), - 'secret' => getenv('AWS_SECRET_ACCESS_KEY'), + 'key' => getenv('AWS_ACCESS_KEY_ID'), + 'secret' => getenv('AWS_SECRET_ACCESS_KEY'), ], ]); $s3result = $S3->putObject([ - 'Bucket' => getenv('AWS_BUCKET'), - 'Key' => 'client_uploads/' . $fileNameToStore, + 'Bucket' => getenv('AWS_BUCKET'), + 'Key' => 'client_uploads/' . $fileNameToStore, 'SourceFile' => $request->file('file') ]); $ObjectURL = $s3result['ObjectURL'] ?? getenv('SITE_URL') . '/not-found'; MembershipAgreementFile::where('id', '>', 0)->delete(); - $membershipAgreementFile = new MembershipAgreementFile(); + $membershipAgreementFile = new MembershipAgreementFile(); $membershipAgreementFile->name = $filenameWithExt; $membershipAgreementFile->path = $ObjectURL; - $membershipAgreementFile->url = $ObjectURL; + $membershipAgreementFile->url = $ObjectURL; $membershipAgreementFile->save(); DB::table('users')->update(['membership_agreement' => 0]); + return $this->successResponse($membershipAgreementFile); } catch (\Exception $ex) { - return $this->errorResponse(__('Failed upload file'), Response::HTTP_BAD_REQUEST, $ex->getMessage()); + return $this->errorResponse( + __('Failed upload file'), + Response::HTTP_BAD_REQUEST, + $ex->getMessage() + ); } } - - public function getMembershipFile() - { - $membershipAgreementFile = MembershipAgreementFile::first(); - return $this->successResponse($membershipAgreementFile); - } } \ No newline at end of file diff --git a/app/Http/Controllers/Api/V1/AuthController.php b/app/Http/Controllers/Api/V1/AuthController.php index 0f50f50a..764d2e52 100644 --- a/app/Http/Controllers/Api/V1/AuthController.php +++ b/app/Http/Controllers/Api/V1/AuthController.php @@ -2,6 +2,7 @@ namespace App\Http\Controllers\Api\V1; +use Carbon\Carbon; use App\Console\Helper; use App\Http\Controllers\Controller; @@ -20,10 +21,13 @@ use App\Models\User; use App\Models\UserAddress; use App\Models\VerifyUser; +use App\Models\UpgradeList; use App\Repositories\UserRepository; use App\Repositories\VerifyUserRepository; +use App\Jobs\TestJob; + use Illuminate\Http\Request; use Illuminate\Http\Response; use Illuminate\Support\Facades\DB; @@ -57,9 +61,62 @@ public function __construct( $this->verifyUserRepo = $verifyUserRepo; } - public function testHash() { - exit(Hash::make('ledgerleapllc')); + public function testJob() { + TestJob::dispatch(); + return 'Test Job!'; + } + + public function devUpgradeList() { + $items = UpgradeList::orderBy('created_at', 'asc')->get(); + if ($items && count($items) > 0) { + foreach ($items as $item) { + echo $item->email . '
'; + } + } + } + + public function devVerifyNode($address) + { + $query = DB::select(" + SELECT + a.user_id, a.node_verified_at, a.signed_file, a.node_status, + b.id, b.email, b.node_verified_at, b.signed_file, + b.node_status, b.has_verified_address + FROM user_addresses AS a + JOIN users AS b + ON a.user_id = b.id + WHERE a.public_address_node = '$address' + "); + + $query = $query[0] ?? []; + $user_id = $query->user_id ?? 0; + + if ($user_id) { + $update = DB::table('user_addresses') + ->where('public_address_node', $address) + ->update( + [ + 'node_verified_at' => '2022-03-18 19:26:51', + 'signed_file' => 'https://casper-assoc-portal-dev.s3.us-east-2.amazonaws.com/signatures/db49744f7535b218c20a48cb833da6a1', + 'node_status' => 'Online' + ] + ); + + $update = DB::table('users') + ->where('id', $user_id) + ->update( + [ + 'node_verified_at' => '2022-03-18 19:26:51', + 'signed_file' => 'https://casper-assoc-portal-dev.s3.us-east-2.amazonaws.com/signatures/db49744f7535b218c20a48cb833da6a1', + 'node_status' => 'Online', + 'has_verified_address' => 1 + ] + ); + } + + return $this->metaSuccess(); } + /** * Auth user function @@ -71,35 +128,50 @@ public function testHash() { public function login(LoginRequest $request) { $user = $this->userRepo->first(['email' => $request->email]); + if ($user && Hash::check($request->password, $user->password)) { if ($user->banned == 1) { - return $this->errorResponse('User banned', Response::HTTP_BAD_REQUEST); + return $this->errorResponse( + 'User banned', + Response::HTTP_BAD_REQUEST + ); } + if ($user->twoFA_login) { $code = strtoupper(Str::random(6)); $user->twoFA_login_active = 1; $user->save(); - VerifyUser::where('email', $user->email)->where('type', VerifyUser::TYPE_LOGIN_TWO_FA)->delete(); - $verify = new VerifyUser(); - $verify->email = $user->email; - $verify->type = VerifyUser::TYPE_LOGIN_TWO_FA; - $verify->code = $code; - $verify->created_at = now(); + + VerifyUser::where('email', $user->email) + ->where('type', VerifyUser::TYPE_LOGIN_TWO_FA) + ->delete(); + + $verify = new VerifyUser(); + $verify->email = $user->email; + $verify->type = VerifyUser::TYPE_LOGIN_TWO_FA; + $verify->code = $code; + $verify->created_at = Carbon::now('UTC'); $verify->save(); + Mail::to($user)->send(new LoginTwoFA($code)); } - $user->last_login_at = now(); + + $user->last_login_at = Carbon::now('UTC'); $user->last_login_ip_address = request()->ip(); $user->save(); - $ipHistory = new IpHistory(); - $ipHistory->user_id = $user->id; + + $ipHistory = new IpHistory(); + $ipHistory->user_id = $user->id; $ipHistory->ip_address = request()->ip(); $ipHistory->save(); Helper::getAccountInfoStandard($user); return $this->createTokenFromUser($user); } - return $this->errorResponse(__('api.error.login_not_found'), Response::HTTP_BAD_REQUEST); + return $this->errorResponse( + __('api.error.login_not_found'), + Response::HTTP_BAD_REQUEST + ); } /** @@ -115,32 +187,36 @@ public function registerEntity(RegisterEntityRequest $request) DB::beginTransaction(); $data = $request->all(); - $data['password'] = bcrypt($request->password); - $data['last_login_at'] = now(); - $data['type'] = User::TYPE_ENTITY; + $data['password'] = bcrypt($request->password); + $data['last_login_at'] = Carbon::now('UTC'); + $data['type'] = User::TYPE_ENTITY; + $user = $this->userRepo->create($data); - $code = generateString(7); + $code = Helper::generateString(7); + $userVerify = $this->verifyUserRepo->updateOrCreate( [ 'email' => $request->email, - 'type' => VerifyUser::TYPE_VERIFY_EMAIL, + 'type' => VerifyUser::TYPE_VERIFY_EMAIL, ], [ - 'code' => $code, - 'created_at' => now() + 'code' => $code, + 'created_at' => Carbon::now('UTC') ] ); + Mail::to($user->email)->send(new UserVerifyMail($code)); DB::commit(); - $user->pending_node = 1; - $user->last_login_at = now(); + $user->pending_node = 1; + $user->last_login_at = Carbon::now('UTC'); $user->last_login_ip_address = request()->ip(); $user->save(); - $ipHistory = new IpHistory(); - $ipHistory->user_id = $user->id; + $ipHistory = new IpHistory(); + $ipHistory->user_id = $user->id; $ipHistory->ip_address = request()->ip(); $ipHistory->save(); + return $this->createTokenFromUser($user); } catch (\Exception $e) { DB::rollBack(); @@ -161,32 +237,36 @@ public function registerIndividual(RegisterIndividualRequest $request) DB::beginTransaction(); $data = $request->all(); - $data['password'] = bcrypt($request->password); - $data['last_login_at'] = now(); - $data['type'] = User::TYPE_INDIVIDUAL; + $data['password'] = bcrypt($request->password); + $data['last_login_at'] = Carbon::now('UTC'); + $data['type'] = User::TYPE_INDIVIDUAL; + $user = $this->userRepo->create($data); - $code = generateString(7); + $code = Helper::generateString(7); + $userVerify = $this->verifyUserRepo->updateOrCreate( [ 'email' => $request->email, - 'type' => VerifyUser::TYPE_VERIFY_EMAIL, + 'type' => VerifyUser::TYPE_VERIFY_EMAIL, ], [ - 'code' => $code, - 'created_at' => now(), + 'code' => $code, + 'created_at' => Carbon::now('UTC'), ] ); + Mail::to($user->email)->send(new UserVerifyMail($code)); DB::commit(); - $user->pending_node = 1; - $user->last_login_at = now(); + $user->pending_node = 1; + $user->last_login_at = Carbon::now('UTC'); $user->last_login_ip_address = request()->ip(); $user->save(); - $ipHistory = new IpHistory(); - $ipHistory->user_id = $user->id; - $ipHistory->ip_address = request()->ip(); + $ipHistory = new IpHistory(); + $ipHistory->user_id = $user->id; + $ipHistory->ip_address = request()->ip(); $ipHistory->save(); + return $this->createTokenFromUser($user); } catch (\Exception $e) { DB::rollBack(); @@ -205,19 +285,35 @@ public function verifyEmail(Request $request) { try { $user = auth()->user(); - $verifyUser = $this->verifyUserRepo->first( - ['code' => $request->code, 'email' => $user->email] - ); + $verifyUser = $this->verifyUserRepo->first([ + 'code' => $request->code, + 'email' => $user->email + ]); + if ($this->checCode($verifyUser)) { - $user->update(['email_verified_at' => now()]); + $user->update(['email_verified_at' => Carbon::now('UTC')]); $verifyUser->delete(); $emailerData = EmailerHelper::getEmailerData(); - EmailerHelper::triggerUserEmail($user->email, 'Welcome to the Casper', $emailerData, $user); + + EmailerHelper::triggerUserEmail( + $user->email, + 'Welcome to the Casper', + $emailerData, + $user + ); + return $this->metaSuccess(); } - return $this->errorResponse(__('api.error.code_not_found'), Response::HTTP_BAD_REQUEST); + + return $this->errorResponse( + __('api.error.code_not_found'), + Response::HTTP_BAD_REQUEST + ); } catch (\Exception $ex) { - return $this->errorResponse(__('api.error.internal_error'), Response::HTTP_INTERNAL_SERVER_ERROR); + return $this->errorResponse( + __('api.error.internal_error'), + Response::HTTP_INTERNAL_SERVER_ERROR + ); } } @@ -236,29 +332,55 @@ public function sendResetLinkEmail(SendResetPasswordMailRequeslRequest $request) 'email' => $request->email, ] ); + if (!$user) { - return $this->errorResponse(__('api.error.email_not_found'), Response::HTTP_BAD_REQUEST); + return $this->successResponse([ + 'success' => false, + 'message' => 'We can\'t find an account associated with that email address. Please check the address and try again.' + ]); } - $code = Str::random(60); - // $url = $request->header('origin') ?? $request->root(); - $url = getenv('SITE_URL'); - $resetUrl = $url . '/update-password?code=' . $code . '&email=' . urlencode($request->email); + + if (!filter_var($request->email, FILTER_VALIDATE_EMAIL)) { + return $this->successResponse([ + 'success' => false, + 'message' => 'Invalid email provided' + ]); + } + + $code = Str::random(60); + $url = getenv('SITE_URL'); + $resetUrl = (string)( + $url . + '/update-password?code=' . + $code . + '&email=' . + urlencode($request->email) + ); + $passwordReset = $this->verifyUserRepo->updateOrCreate( [ 'email' => $user->email, - 'type' => VerifyUser::TYPE_RESET_PASSWORD, + 'type' => VerifyUser::TYPE_RESET_PASSWORD, ], [ - 'code' => $code, - 'created_at' => now(), + 'code' => $code, + 'created_at' => Carbon::now('UTC'), ] ); + if ($passwordReset) { Mail::to($request->email)->send(new ResetPasswordMail($resetUrl)); } - return $this->metaSuccess(); + + return $this->successResponse([ + 'success' => true, + 'message' => 'A password reset link has been sent to your email.' + ]); } catch (\Exception $ex) { - return $this->errorResponse(__('api.error.internal_error'), Response::HTTP_INTERNAL_SERVER_ERROR); + return $this->errorResponse( + __('api.error.internal_error'), + Response::HTTP_INTERNAL_SERVER_ERROR + ); } } @@ -274,23 +396,37 @@ public function resetPassword(ResetPasswordRequest $request) try { $passwordReset = $this->verifyUserRepo->first( [ - 'code' => $request->code, - 'type' => VerifyUser::TYPE_RESET_PASSWORD, + 'code' => $request->code, + 'type' => VerifyUser::TYPE_RESET_PASSWORD, 'email' => $request->email ] ); + if ($this->checCode($passwordReset)) { DB::beginTransaction(); - $this->userRepo->updateConditions(['password' => bcrypt($request->password)], ['email' => $passwordReset->email]); + $this->userRepo->updateConditions( + ['password' => bcrypt($request->password)], + ['email' => $passwordReset->email] + ); + $passwordReset->delete(); DB::commit(); return $this->metaSuccess(); } + DB::rollBack(); - return $this->errorResponse(__('api.error.code_not_found'), Response::HTTP_BAD_REQUEST); + + return $this->errorResponse( + __('api.error.code_not_found'), + Response::HTTP_BAD_REQUEST + ); } catch (\Exception $ex) { DB::rollBack(); - return $this->errorResponse(__('api.error.internal_error'), Response::HTTP_INTERNAL_SERVER_ERROR); + + return $this->errorResponse( + __('api.error.internal_error'), + Response::HTTP_INTERNAL_SERVER_ERROR + ); } } /** @@ -303,21 +439,23 @@ public function resetPassword(ResetPasswordRequest $request) public function resendVerifyEmail(Request $request) { try { - $user = auth()->user(); - $code = generateString(7); + $user = auth()->user(); + $code = Helper::generateString(7); $userVerify = $this->verifyUserRepo->updateOrCreate( [ 'email' => $user->email, - 'type' => VerifyUser::TYPE_VERIFY_EMAIL, + 'type' => VerifyUser::TYPE_VERIFY_EMAIL, ], [ - 'code' => $code, - 'created_at' => now() + 'code' => $code, + 'created_at' => Carbon::now('UTC') ] ); + if ($userVerify) { Mail::to($user->email)->send(new UserVerifyMail($code)); } + return $this->metaSuccess(); } catch (\Exception $e) { throw $e; @@ -328,35 +466,55 @@ public function registerSubAdmin(Request $request) { $validator = Validator::make($request->all(), [ 'first_name' => 'required|regex:/^[A-Za-z. ]{1,255}$/', - 'last_name' => 'required|regex:/^[A-Za-z. ]{1,255}$/', - 'email' => 'required|email|max:256', - 'code' => 'required', - 'password' => 'required|min:8|max:80', + 'last_name' => 'required|regex:/^[A-Za-z. ]{1,255}$/', + 'email' => 'required|email|max:256', + 'code' => 'required', + 'password' => 'required|min:8|max:80', ]); if ($validator->fails()) { return $this->validateResponse($validator->errors()); } - $user = User::where('email', $request->email)->where('member_status', 'invited')->where('role', 'sub-admin')->first(); + + $user = User::where('email', $request->email) + ->where('member_status', 'invited') + ->where('role', 'sub-admin') + ->first(); + if (!$user) { - return $this->errorResponse('There is no admin user with this email', Response::HTTP_BAD_REQUEST); + return $this->errorResponse( + 'There is no admin user with this email', + Response::HTTP_BAD_REQUEST + ); } - $verify = VerifyUser::where('email', $request->email)->where('type', VerifyUser::TYPE_INVITE_ADMIN)->where('code', $request->code)->first(); + + $verify = VerifyUser::where('email', $request->email) + ->where('type', VerifyUser::TYPE_INVITE_ADMIN) + ->where('code', $request->code) + ->first(); + if (!$verify) { - return $this->errorResponse('Fail register sub-amdin', Response::HTTP_BAD_REQUEST); + return $this->errorResponse( + 'Fail register sub-amdin', + Response::HTTP_BAD_REQUEST + ); } - $user->first_name = $request->first_name; - $user->last_name = $request->last_name; - $user->password = bcrypt($request->password); - $user->last_login_at = now(); + + $user->first_name = $request->first_name; + $user->last_name = $request->last_name; + $user->password = bcrypt($request->password); + $user->last_login_at = Carbon::now('UTC'); $user->last_login_ip_address = request()->ip(); - $user->member_status = 'active'; + $user->member_status = 'active'; $user->save(); - $ipHistory = new IpHistory(); - $ipHistory->user_id = $user->id; + + $ipHistory = new IpHistory(); + $ipHistory->user_id = $user->id; $ipHistory->ip_address = request()->ip(); $ipHistory->save(); + $verify->delete(); + return $this->createTokenFromUser($user); } @@ -365,6 +523,7 @@ public function createTokenFromUser($user, $info = []) Token::where([ 'user_id' => $user->id ])->delete(); + $token = $user->createToken(config('auth.secret_code')); return $this->responseToken($token, $user->toArray()); } @@ -378,6 +537,11 @@ public function createTokenFromUser($user, $info = []) */ private function checCode($verifyUser) { - return ($verifyUser && $verifyUser->created_at >= now()->subMinutes(VerifyUser::TOKEN_LIFETIME)); + return ( + $verifyUser && + $verifyUser->created_at >= Carbon::now('UTC')->subMinutes( + VerifyUser::TOKEN_LIFETIME + ) + ); } -} +} \ No newline at end of file diff --git a/app/Http/Controllers/Api/V1/ContactController.php b/app/Http/Controllers/Api/V1/ContactController.php index 7e9e2187..13137f6f 100644 --- a/app/Http/Controllers/Api/V1/ContactController.php +++ b/app/Http/Controllers/Api/V1/ContactController.php @@ -6,6 +6,7 @@ use App\Mail\ContactUsMail; use App\Models\ContactRecipient; use App\Models\ContactUs; +use App\Models\UpgradeList; use Illuminate\Http\Request; use Illuminate\Http\Response; use Illuminate\Support\Facades\Mail; @@ -13,42 +14,67 @@ class ContactController extends Controller { + public function submitUpgradeList(Request $request) + { + $validator = Validator::make($request->all(), [ + 'email' => 'required|email' + ]); + + if ($validator->fails()) { + return $this->validateResponse($validator->errors()); + } + + $email = $request->email; + $record = UpgradeList::where('email', $email)->first(); + + if ($record) { + return $this->errorResponse( + 'This email already exists', + Response::HTTP_BAD_REQUEST + ); + } + + $record = new UpgradeList; + $record->email = $email; + $record->save(); + + return $this->metaSuccess(); + } + public function submitContact(Request $request) { $user_id = null; - if(auth()->user()) { + + if (auth()->user()) { $user_id = auth()->user()->id; } + $validator = Validator::make($request->all(), [ - 'name' => 'required|string|max:255', - 'email' => 'required|email', + 'name' => 'required|string|max:255', + 'email' => 'required|email', 'message' => 'required', ]); + if ($validator->fails()) { return $this->validateResponse($validator->errors()); } + $contactUs = new ContactUs(); $contactUs->user_id = $user_id; - $contactUs->name = $request->name; - $contactUs->email = $request->email; + $contactUs->name = $request->name; + $contactUs->email = $request->email; $contactUs->message = $request->message; $contactUs->save(); - $contactRecipients = ContactRecipient::get(); + + $contactRecipients = ContactRecipient::get(); + if (count($contactRecipients) > 0) { foreach ($contactRecipients as $item) { Mail::to($item->email)->send(new ContactUsMail($contactUs)); } } - return $this->metaSuccess(); - } - public function getContactRecipients(Request $request) - { - $limit = $request->limit ?? 50; - $sort_key = $request->sort_key ?? 'created_at'; - $sort_direction = $request->sort_direction ?? 'desc'; - $contactRecipients = ContactRecipient::orderBy($sort_key, $sort_direction)->paginate($limit); - return $this->successResponse($contactRecipients); + return $this->metaSuccess(); } public function addContactRecipients(Request $request) @@ -56,12 +82,18 @@ public function addContactRecipients(Request $request) $validator = Validator::make($request->all(), [ 'email' => 'required|email', ]); + if ($validator->fails()) { return $this->validateResponse($validator->errors()); } + $contactRecipient = ContactRecipient::where('email', $request->email)->first(); + if ($contactRecipient) { - return $this->errorResponse('This email has already exist', Response::HTTP_BAD_REQUEST); + return $this->errorResponse( + 'This email has already exist', + Response::HTTP_BAD_REQUEST + ); } else { $contactRecipient = new ContactRecipient(); $contactRecipient->email = $request->email; diff --git a/app/Http/Controllers/Api/V1/DiscussionController.php b/app/Http/Controllers/Api/V1/DiscussionController.php index 6302a923..b230d9c8 100644 --- a/app/Http/Controllers/Api/V1/DiscussionController.php +++ b/app/Http/Controllers/Api/V1/DiscussionController.php @@ -21,6 +21,7 @@ use App\Models\DiscussionComment; use App\Models\DiscussionPin; use App\Models\DiscussionRemoveNew; +use App\Models\DiscussionVote; use Carbon\Carbon; @@ -57,9 +58,15 @@ public function getTrending(Request $request) if (Helper::isAccessBlocked($user, 'discussions')) return $this->successResponse(['data' => []]); - $limit = $request->limit ?? 50; - $trendings = Discussion::where('likes', '!=', 0)->where('is_draft', 0)->take(9)->orderBy('likes', 'desc')->paginate($limit); - $count = Discussion::where('likes', '!=', 0)->where('is_draft', 0)->orderBy('likes', 'desc')->count(); + $trendings = Discussion::where('likes', '!=', 0) + ->where('is_draft', 0) + ->take(9) + ->orderBy('likes', 'desc') + ->get(); + $count = Discussion::where('likes', '!=', 0) + ->where('is_draft', 0) + ->orderBy('likes', 'desc') + ->count(); if ($count >= 9) { return $this->successResponse($trendings); } else { @@ -71,10 +78,8 @@ public function getTrending(Request $request) ->where('is_draft', 0) ->take($remains)->orderBy('id', 'desc')->get(); $trendingArray = $trendings->toArray(); - $trendingArray['data'] = array_merge($trendingArray['data'], $news->toArray()); - return $this->successResponse([ - 'data' => $trendingArray['data'] - ]); + $trendingArray = array_merge($trendingArray, $news->toArray()); + return $this->successResponse($trendingArray); } } @@ -85,7 +90,6 @@ public function getDiscussions(Request $request) if (Helper::isAccessBlocked($user, 'discussions')) return $this->successResponse(['data' => []]); - $data = array(); $limit = $request->limit ?? 50; $data = Discussion::with(['user', 'user.profile'])->where('discussions.is_draft', 0) ->leftJoin('discussion_pins', function ($query) use ($user) { @@ -250,7 +254,7 @@ public function createComment(Request $request, $id) if (Helper::isAccessBlocked($user, 'discussions')) return $this->errorResponse('Your access is blocked', Response::HTTP_BAD_REQUEST); - $data = array(); + $data = []; $validator = Validator::make($request->all(), [ 'description' => 'required' ]); @@ -282,7 +286,6 @@ public function updateComment(Request $request, $id) if (Helper::isAccessBlocked($user, 'discussions')) return $this->errorResponse('Your access is blocked', Response::HTTP_BAD_REQUEST); - $data = array(); $validator = Validator::make($request->all(), [ 'description' => 'required', 'comment_id' => 'required' @@ -290,22 +293,47 @@ public function updateComment(Request $request, $id) if ($validator->fails()) { return $this->validateResponse($validator->errors()); } - $comment = DiscussionComment::where('discussion_id', $request->comment_id)->where('user_id', $user->id)->first(); + $comment = DiscussionComment::where('id', $request->comment_id) + ->where('discussion_id', $id) + ->where('user_id', $user->id)->first(); if ($comment) { $comment->description = $request->description; + $comment->edited_at = Carbon::now('UTC'); $comment->save(); return $this->successResponse($comment); } return $this->errorResponse('Invalid discussion id', Response::HTTP_BAD_REQUEST); } + public function deleteComment($id, $commentId) + { + $user = auth()->user()->load(['pagePermissions']); + if (Helper::isAccessBlocked($user, 'discussions')) + return $this->errorResponse('Your access is blocked', Response::HTTP_BAD_REQUEST); + + $comment = DiscussionComment::where('id', $commentId) + ->where('discussion_id', $id) + ->where(function ($query) use ($user) { + if ($user->role != 'admin') { + $query->where('user_id', $user->id); + } + }) + ->first(); + if ($comment) { + $comment->description = '

Comment deleted

'; + $comment->deleted_at = Carbon::now('UTC'); + $comment->save(); + return $this->metaSuccess(); + } + return $this->errorResponse('Invalid discussion id', Response::HTTP_BAD_REQUEST); + } + public function setVote(Request $request, $id) { $user = auth()->user()->load(['pagePermissions']); if (Helper::isAccessBlocked($user, 'discussions')) return $this->errorResponse('Your access is blocked', Response::HTTP_BAD_REQUEST); - $data = array(); $validator = Validator::make($request->all(), [ 'is_like' => 'required|boolean' ]); @@ -361,7 +389,6 @@ public function setPin(Request $request, $id) if (Helper::isAccessBlocked($user, 'discussions')) return $this->errorResponse('Your access is blocked', Response::HTTP_BAD_REQUEST); - $data = array(); $pinned = $this->discussionPinRepo->first(['discussion_id' => $id, 'user_id' => $user->id]); if ($pinned == null) { $this->discussionPinRepo->create(['discussion_id' => $id, 'user_id' => $user->id]); @@ -377,7 +404,7 @@ public function removeNewMark(Request $request, $id) if (Helper::isAccessBlocked($user, 'discussions')) return $this->errorResponse('Your access is blocked', Response::HTTP_BAD_REQUEST); - $this->discussionRemoveNewRepo->deleteConditions([['created_at', '<=', Carbon::now()->subDays(3)]]); + $this->discussionRemoveNewRepo->deleteConditions([['created_at', '<=', Carbon::now('UTC')->subDays(3)]]); $this->discussionRemoveNewRepo->create(['discussion_id' => $id, 'user_id' => $user->id]); return $this->metaSuccess(); @@ -412,6 +439,32 @@ public function getDraftDiscussions(Request $request) return $this->successResponse($data); } + public function deleteDiscussion($id) + { + $user = auth()->user()->load(['pagePermissions']); + if (Helper::isAccessBlocked($user, 'discussions')) + return $this->errorResponse('Your access is blocked', Response::HTTP_BAD_REQUEST); + + $discussion = Discussion::where('id', $id) + ->where(function ($query) use ($user) { + if ($user->role != 'admin') { + $query->where('user_id', $user->id); + } + }) + ->first(); + if (!$discussion) { + return $this->errorResponse('Can not delete discussion', Response::HTTP_BAD_REQUEST); + } + + DiscussionComment::where('discussion_id', $discussion->id)->delete(); + DiscussionPin::where('discussion_id', $discussion->id)->delete(); + DiscussionRemoveNew::where('discussion_id', $discussion->id)->delete(); + DiscussionVote::where('discussion_id', $discussion->id)->delete(); + $discussion->delete(); + + return $this->metaSuccess(); + } + public function deleteDraftDiscussions($id) { $user = auth()->user()->load(['pagePermissions']); diff --git a/app/Http/Controllers/Api/V1/HelloSignController.php b/app/Http/Controllers/Api/V1/HelloSignController.php index 6d8aba0f..ed388b69 100644 --- a/app/Http/Controllers/Api/V1/HelloSignController.php +++ b/app/Http/Controllers/Api/V1/HelloSignController.php @@ -15,24 +15,31 @@ class HelloSignController extends Controller public function hellosignHook(Request $request) { $payload = $request->get('json'); - if (!$payload) return "error"; + + if (!$payload) { + return "error"; + } $data = json_decode($payload, true); $api_key = env('HELLOSIGN_API_KEY_HOOK'); - if (!is_array($data)) return "error"; + if (!is_array($data)) { + return "error"; + } // hellosign test check $callback_test = $data['event']['event_type'] ?? ''; - if ($callback_test == 'callback_test') { return "Hello API Event Received"; } $md5_header_check = base64_encode(hash_hmac('md5', $payload, $api_key)); $md5_header = $request->header('Content-MD5'); - if ($md5_header != $md5_header_check) + + if ($md5_header != $md5_header_check) { return "error"; + } + // Valid Request if ( isset($data['event']) && @@ -43,15 +50,15 @@ public function hellosignHook(Request $request) $filepath = 'hellosign/hellosign_' . $signature_request_id . '.pdf'; $client = new \HelloSign\Client($api_key); - $client->getFiles($signature_request_id, $filepath, \HelloSign\SignatureRequest::FILE_TYPE_PDF); $user = User::where('signature_request_id', $signature_request_id)->first(); if ($user) { - $user->hellosign_form = $filepath; + $user->hellosign_form = ''; $user->save(); } - return "Hello API Event Received"; } + + return "Hello API Event Received"; } } diff --git a/app/Http/Controllers/Api/V1/MetricController.php b/app/Http/Controllers/Api/V1/MetricController.php deleted file mode 100644 index 586c18bf..00000000 --- a/app/Http/Controllers/Api/V1/MetricController.php +++ /dev/null @@ -1,439 +0,0 @@ -user()->load(['pagePermissions']); - /* - if (Helper::isAccessBlocked($user, 'nodes')) - return $this->successResponse([]); - */ - $public_address_node = $request->get('public_address_node'); - - if (!$public_address_node) { - $public_address_node = $user->public_address_node; - } - - $isTotal = (int) $request->get('isTotal'); - - $max_update_responsiveness = DB::select(" - SELECT max(update_responsiveness) as max_update_responsiveness FROM - ( - SELECT MAX(update_responsiveness) as update_responsiveness FROM metric - UNION - SELECT MAX(update_responsiveness) as update_responsiveness FROM node_info - ) AS results;" - ); - $max_update_responsiveness = $max_update_responsiveness[0]->max_update_responsiveness ?? 0; - - $max_peers = DB::select(" - SELECT max(peers) as max_peers FROM ( - SELECT MAX(peers) as peers FROM metric - UNION - SELECT MAX(peers) as peers FROM node_info - ) AS results;" - ); - $max_peers = $max_peers[0]->max_peers ?? 0; - $max_block_height = Node::max('block_height'); - $max_uptime = DB::select(" - SELECT max(uptime) as max_uptime FROM ( - SELECT MAX(uptime) as uptime FROM metric - UNION - SELECT MAX(uptime) as uptime FROM node_info - ) AS results;" - ); - $max_uptime = $max_uptime[0]->max_uptime ?? 0; - $latest = Node::where('node_address', strtolower($public_address_node))->whereNotnull('protocol_version')->orderBy('created_at', 'desc')->first(); - - if (!$latest) { - $latest = new Node(); - } - - $latest_block_height = $latest->block_height ?? null; - $latest_update_responsiveness = $latest->update_responsiveness ?? null; - $latest_peers = $latest->peers ?? null; - - $metric = Metric::where('user_id', $user->id)->first(); - - if (!$metric) { - $metric = new Metric(); - } - - $metric_uptime = $metric->uptime ?? null; - $metric_block_height = $metric->block_height_average ? ($max_block_height - $metric->block_height_average) : null; - $metric_update_responsiveness = $metric->update_responsiveness ?? null; - $metric_peers = $metric->peers ?? null; - - $nodeInfo = NodeInfo::where('node_address', strtolower($public_address_node))->first(); - - if (!$nodeInfo) { - $nodeInfo = new NodeInfo(); - } - - $latest_uptime = $nodeInfo->uptime ?? null; - $nodeInfo_uptime = $nodeInfo->uptime ?? null; - $nodeInfo_block_height = $nodeInfo->block_height ?? null; - $nodeInfo_update_responsiveness = $nodeInfo->update_responsiveness ?? null; - $nodeInfo_peers = $nodeInfo->peers ?? null; - - $metric->avg_uptime = $nodeInfo_uptime ?? $metric_uptime; - $metric->avg_block_height_average = $nodeInfo_block_height ?? $metric_block_height; - $metric->avg_update_responsiveness = $nodeInfo_update_responsiveness ?? $metric_update_responsiveness; - $metric->avg_peers = $nodeInfo_peers ?? $metric_peers; - - $metric->max_peers = $max_peers; - $metric->max_update_responsiveness = $max_update_responsiveness; - $metric->max_block_height_average = $max_block_height; - $metric->max_uptime = $max_uptime; - - $metric->peers = $latest_peers ?? $metric_peers; - $metric->update_responsiveness = $latest_update_responsiveness ?? $metric_update_responsiveness; - $metric->block_height_average = $latest_block_height ?? $metric_block_height; - $metric->uptime = $latest_uptime ?? $metric_uptime; - - $monitoringCriteria = MonitoringCriteria::get(); - $nodeInfo = NodeInfo::where('node_address', strtolower($public_address_node))->first(); - - $userAddress = UserAddress::where('public_address_node', strtolower($public_address_node)) - ->where('user_id', $user->id) - ->first(); - - $rank = $user->rank; - - if ($userAddress) { - $rank = $userAddress->rank; - } - - $totalCount = UserAddress::select([ - 'users.id as user_id', - 'user_addresses.public_address_node', - 'user_addresses.is_fail_node', - 'user_addresses.rank' - ]) - ->join('users', 'users.id', '=', 'user_addresses.user_id') - ->where('users.banned', 0) - ->whereNotNull('user_addresses.public_address_node') - ->get() - ->count(); - - $delegators = $stake_amount = $self_stake_amount = 0; - if ($nodeInfo) { - $delegators = $nodeInfo->delegators_count; - $stake_amount = $nodeInfo->total_staked_amount; - $self_stake_amount = $nodeInfo->self_staked_amount; - } - - $mbs = NodeInfo::max('mbs'); - $metric->mbs = $mbs; - $metric->rank = $rank; - $metric->totalCount = $totalCount; - $metric->delegators = $delegators; - $metric->stake_amount = $stake_amount; - $metric->self_stake_amount = $self_stake_amount; - $metric['node_status'] = $user->node_status; - $metric['monitoring_criteria'] = $monitoringCriteria; - - $setting = Setting::where('name', 'peers')->first(); - - if ($setting) { - $metric['peers_setting'] = (int) $setting->value; - } else { - $metric['peers_setting'] = 0; - } - - $addresses = UserAddress::where('user_id', $user->id)->get(); - $metric['addresses'] = $addresses; - - if ($isTotal) { - $tempRank = $stake_amount = $self_stake_amount = $delegators = 0; - if ($addresses && count($addresses) > 0) { - $tempRank = UserAddress::get()->count(); - foreach ($addresses as $address) { - if ($tempRank > (int) $address->rank) { - $tempRank = (int) $address->rank; - } - } - } - - if ($tempRank > 0) { - $metric->rank = $tempRank; - } - - if ($addresses && count($addresses) > 0) { - foreach ($addresses as $address) { - $nodeInfo = NodeInfo::where('node_address', strtolower($address->public_address_node))->first(); - if ($nodeInfo) { - $stake_amount += $nodeInfo->total_staked_amount; - $delegators += $nodeInfo->delegators_count; - $self_stake_amount += $nodeInfo->self_staked_amount; - } - } - } - $metric->delegators = $delegators; - $metric->stake_amount = $stake_amount; - $metric->self_stake_amount = $self_stake_amount; - } - - return $this->successResponse($metric); - } - - public function updateMetric(Request $request, $id) - { - $validator = Validator::make($request->all(), [ - 'uptime' => 'nullable|numeric|between:0,100', - ]); - if ($validator->fails()) return $this->validateResponse($validator->errors()); - - $user = User::where('id', $id)->where('role', 'member')->first(); - if (!$user) return $this->errorResponse('User not found', Response::HTTP_BAD_REQUEST); - - $metric = Metric::where('user_id', $id)->first(); - if (!$metric) $metric = new Metric(); - if (isset($request->uptime) && $request->uptime != null) - $metric->uptime = $request->uptime; - if (isset($request->block_height_average) && $request->block_height_average != null) - $metric->block_height_average = $request->block_height_average; - if (isset($request->update_responsiveness) && $request->update_responsiveness != null) - $metric->update_responsiveness = $request->update_responsiveness; - if (isset($request->peers) && $request->peers != null) - $metric->peers = $request->peers; - $metric->user_id = $id; - $metric->save(); - return $this->successResponse($metric); - } - - public function getMetricUser($id) - { - $user = User::find($id); - if (!$user) return $this->successResponse([]); - - $max_update_responsiveness = DB::select("SELECT max(update_responsiveness) as max_update_responsiveness FROM - ( - SELECT MAX(update_responsiveness) as update_responsiveness FROM metric - UNION - SELECT MAX(update_responsiveness) as update_responsiveness FROM node_info - ) AS results; - "); - $max_update_responsiveness = $max_update_responsiveness[0]->max_update_responsiveness ?? 0; - - $max_peers = DB::select(" - SELECT max(peers) as max_peers FROM - ( - SELECT MAX(peers) as peers FROM metric - UNION - SELECT MAX(peers) as peers FROM node_info - ) AS results; - "); - $max_peers = $max_peers[0]->max_peers ?? 0; - $max_block_height = Node::max('block_height'); - $max_uptime = DB::select(" - SELECT max(uptime) as max_uptime FROM - ( - SELECT MAX(uptime) as uptime FROM metric - UNION - SELECT MAX(uptime) as uptime FROM node_info - ) AS results; - "); - $max_uptime = $max_uptime[0]->max_uptime ?? 0; - $latest = Node::where('node_address', strtolower($user->public_address_node)) - ->whereNotnull('protocol_version') - ->orderBy('created_at', 'desc') - ->first(); - - if (!$latest) $latest = new Node(); - $latest_block_height = $latest->block_height ?? null; - $latest_update_responsiveness = $latest->update_responsiveness ?? null; - $latest_peers = $latest->peers ?? null; - - $metric = Metric::where('user_id', $user->id)->first(); - if (!$metric) $metric = new Metric(); - - $metric_uptime = $metric->uptime ?? null; - $metric_block_height = $metric->block_height_average ? ($max_block_height - $metric->block_height_average) : null; - $metric_update_responsiveness = $metric->update_responsiveness ?? null; - $metric_peers = $metric->peers ?? null; - - $nodeInfo = NodeInfo::where('node_address', strtolower($user->public_address_node))->first(); - if (!$nodeInfo) $nodeInfo = new NodeInfo(); - - $latest_uptime = $nodeInfo->uptime ?? null; - $nodeInfo_uptime = $nodeInfo->uptime ?? null; - $nodeInfo_block_height = $nodeInfo->block_height ?? null; - $nodeInfo_update_responsiveness = $nodeInfo->update_responsiveness ?? null; - $nodeInfo_peers = $nodeInfo->peers ?? null; - - $metric->avg_uptime = $nodeInfo_uptime ?? $metric_uptime; - $metric->avg_block_height_average = $nodeInfo_block_height ?? $metric_block_height; - $metric->avg_update_responsiveness = $nodeInfo_update_responsiveness ?? $metric_update_responsiveness; - $metric->avg_peers = $nodeInfo_peers ?? $metric_peers; - - $metric->max_peers = $max_peers; - $metric->max_update_responsiveness = $max_update_responsiveness; - $metric->max_block_height_average = $max_block_height; - $metric->max_uptime = $max_uptime; - - $metric->peers = $latest_peers ?? $metric_peers; - $metric->update_responsiveness = $latest_update_responsiveness ?? $metric_update_responsiveness; - $metric->block_height_average = $latest_block_height ?? $metric_block_height; - $metric->uptime = $latest_uptime ?? $metric_uptime; - - $monitoringCriteria = MonitoringCriteria::get(); - $nodeInfo = NodeInfo::where('node_address', strtolower($user->public_address_node))->first(); - - $rank = $user->rank; - - $totalCount = User::select([ - 'id as user_id', - 'public_address_node', - 'is_fail_node', - 'rank', - ]) - ->where('banned', 0) - ->whereNotNull('public_address_node') - ->get() - ->count(); - - $delegators = $stake_amount = $self_stake_amount = 0; - if ($nodeInfo) { - $delegators = $nodeInfo->delegators_count; - $stake_amount = $nodeInfo->total_staked_amount; - $self_stake_amount = $nodeInfo->self_staked_amount; - } - $mbs = NodeInfo::max('mbs'); - $metric->mbs = $mbs; - $metric->rank = $rank; - $metric->totalCount = $totalCount; - $metric->delegators = $delegators; - $metric->stake_amount = $stake_amount; - $metric->self_stake_amount = $self_stake_amount; - $metric['node_status'] = $user->node_status; - $metric['monitoring_criteria'] = $monitoringCriteria; - - return $this->successResponse($metric); - } - - public function getMetricUserByNodeName($node) - { - $node = strtolower($node); - $userAddress = UserAddress::with('user') - ->has('user') - ->where('public_address_node', $node) - ->first(); - - if ($userAddress && isset($userAddress->user) && $userAddress->user) { - $user = $userAddress->user; - $public_address_node = strtolower($userAddress->public_address_node); - - $max_update_responsiveness = DB::select(" - SELECT max(update_responsiveness) as max_update_responsiveness FROM - ( - SELECT MAX(update_responsiveness) as update_responsiveness FROM metric - UNION - SELECT MAX(update_responsiveness) as update_responsiveness FROM node_info - ) AS results;" - ); - $max_update_responsiveness = $max_update_responsiveness[0]->max_update_responsiveness ?? 0; - - $max_peers = DB::select(" - SELECT max(peers) as max_peers FROM - ( - SELECT MAX(peers) as peers FROM metric - UNION - SELECT MAX(peers) as peers FROM node_info - ) AS results;" - ); - $max_peers = $max_peers[0]->max_peers ?? 0; - $max_block_height = Node::max('block_height'); - $max_uptime = DB::select(" - SELECT max(uptime) as max_uptime FROM - ( - SELECT MAX(uptime) as uptime FROM metric - UNION - SELECT MAX(uptime) as uptime FROM node_info - ) AS results;" - ); - $max_uptime = $max_uptime[0]->max_uptime ?? 0; - - $latest = Node::where('node_address', strtolower($public_address_node))->whereNotnull('protocol_version')->orderBy('created_at', 'desc')->first(); - if (!$latest) $latest = new Node(); - - $latest_block_height = $latest->block_height ?? null; - $latest_update_responsiveness = $latest->update_responsiveness ?? null; - $latest_peers = $latest->peers ?? null; - - $metric = Metric::where('user_id', $user->id)->first(); - if (!$metric) $metric = new Metric(); - $metric_uptime = $metric->uptime ?? null; - $metric_block_height = $metric->block_height_average ? ($max_block_height - $metric->block_height_average) : null; - $metric_update_responsiveness = $metric->update_responsiveness ?? null; - $metric_peers = $metric->peers ?? null; - - $nodeInfo = NodeInfo::where('node_address', strtolower($public_address_node))->first(); - if (!$nodeInfo) $nodeInfo = new NodeInfo(); - - $latest_uptime = $nodeInfo->uptime ?? null; - $nodeInfo_uptime = $nodeInfo->uptime ?? null; - $nodeInfo_block_height = $nodeInfo->block_height ?? null; - $nodeInfo_peers = $nodeInfo->peers ?? null; - $nodeInfo_update_responsiveness = $nodeInfo->update_responsiveness ?? null; - - $metric->avg_uptime = $nodeInfo_uptime ?? $metric_uptime; - $metric->avg_block_height_average = $nodeInfo_block_height ?? $metric_block_height; - $metric->avg_update_responsiveness = $nodeInfo_update_responsiveness ?? $metric_update_responsiveness; - $metric->avg_peers = $nodeInfo_peers ?? $metric_peers; - - $metric->max_peers = $max_peers; - $metric->max_update_responsiveness = $max_update_responsiveness; - $metric->max_block_height_average = $max_block_height; - $metric->max_uptime = $max_uptime; - - $metric->peers = $latest_peers ?? $metric_peers; - $metric->update_responsiveness = $latest_update_responsiveness ?? $metric_update_responsiveness; - $metric->block_height_average = $latest_block_height ?? $metric_block_height; - $metric->uptime = $latest_uptime ?? $metric_uptime; - - $monitoringCriteria = MonitoringCriteria::get(); - $nodeInfo = NodeInfo::where('node_address', strtolower($public_address_node))->first(); - $rank = $userAddress->rank; - $delegators = $stake_amount = $self_stake_amount = $is_open_port = 0; - if ($nodeInfo) { - $delegators = $nodeInfo->delegators_count; - $stake_amount = $nodeInfo->total_staked_amount; - $self_stake_amount = $nodeInfo->self_staked_amount; - $is_open_port = $nodeInfo->is_open_port; - } - $mbs = NodeInfo::max('mbs'); - $metric->mbs = $mbs; - $metric->rank = $rank; - $metric->is_open_port = $is_open_port; - $metric->delegators = $delegators; - $metric->self_stake_amount = $self_stake_amount; - $metric['node_status'] = $user->node_status; - $metric['monitoring_criteria'] = $monitoringCriteria; - return $this->successResponse($metric); - } - return $this->successResponse([]); - } -} \ No newline at end of file diff --git a/app/Http/Controllers/Api/V1/NotificationController.php b/app/Http/Controllers/Api/V1/NotificationController.php index fd270335..eea65c61 100644 --- a/app/Http/Controllers/Api/V1/NotificationController.php +++ b/app/Http/Controllers/Api/V1/NotificationController.php @@ -62,15 +62,15 @@ public function dismiss($id) $notificationView = new notificationView(); $notificationView->user_id = $user->id; $notificationView->notification_id = $id; - $notificationView->first_view_at = now(); - $notificationView->dismissed_at = now(); + $notificationView->first_view_at = Carbon::now('UTC'); + $notificationView->dismissed_at = Carbon::now('UTC'); $notificationView->save(); $notification->total_views = $notification->total_views + 1; $notification->save(); } else { if (!$notificationView->dismissed_at) { - $notificationView->dismissed_at = now(); + $notificationView->dismissed_at = Carbon::now('UTC'); $notificationView->save(); } } @@ -90,8 +90,8 @@ public function clickCTA($id) $notificationView = new notificationView(); $notificationView->user_id = $user->id; $notificationView->notification_id = $id; - $notificationView->first_view_at = now(); - $notificationView->cta_click_at = now(); + $notificationView->first_view_at = Carbon::now('UTC'); + $notificationView->cta_click_at = Carbon::now('UTC'); $notificationView->cta_click_count = $notificationView->cta_click_count + 1; $notificationView->save(); @@ -99,7 +99,7 @@ public function clickCTA($id) $notification->save(); } else { if (!$notificationView->cta_click_at) { - $notificationView->cta_click_at = now(); + $notificationView->cta_click_at = Carbon::now('UTC'); } $notificationView->cta_click_count = $notificationView->cta_click_count + 1; $notificationView->save(); @@ -120,7 +120,7 @@ public function updateView($id) $notificationView = new notificationView(); $notificationView->user_id = $user->id; $notificationView->notification_id = $id; - $notificationView->first_view_at = now(); + $notificationView->first_view_at = Carbon::now('UTC'); $notificationView->save(); $notification->total_views = $notification->total_views + 1; @@ -203,7 +203,7 @@ public function createNotification(Request $request) return $this->validateResponse($validator->errors()); } - $now = Carbon::now()->format('Y-m-d'); + $now = Carbon::now('UTC')->format('Y-m-d'); $notification = new Notification(); $startDate = $request->start_date; $endDate = $request->end_date; @@ -295,7 +295,7 @@ public function updateNotification(Request $request, $id) return $this->validateResponse($validator->errors()); } - $now = Carbon::now()->format('Y-m-d'); + $now = Carbon::now('UTC')->format('Y-m-d'); $notification = Notification::where('id', $id)->first(); if (!$notification) { return $this->errorResponse('Not found notification', Response::HTTP_BAD_REQUEST); @@ -364,7 +364,6 @@ public function getNotificationDetail($id) if (!$notification) { return $this->errorResponse('Not found notification', Response::HTTP_BAD_REQUEST); } - return $this->successResponse($notification); } } diff --git a/app/Http/Controllers/Api/V1/PerkController.php b/app/Http/Controllers/Api/V1/PerkController.php index e3986122..db4a0f4a 100644 --- a/app/Http/Controllers/Api/V1/PerkController.php +++ b/app/Http/Controllers/Api/V1/PerkController.php @@ -9,6 +9,8 @@ use App\Models\Perk; use App\Models\PerkResult; +use App\Jobs\PerkNotification; + use Carbon\Carbon; use Illuminate\Http\Request; @@ -25,29 +27,37 @@ public function createPerk(Request $request) { 'title' => 'required|string|max:70', 'content' => 'required', 'action_link' => 'required|url', - 'image' => 'required|mimes:jpeg,jpg,png,gif|max:100000', + // 'image' => 'required|mimes:pdf,jpeg,jpg,png,gif,txt,rtf|max:200000', + 'image' => 'required|mimes:pdf,jpeg,jpg,png,gif,txt,rtf|max:2048', 'start_date' => 'required|nullable|date_format:Y-m-d', 'end_date' => 'required|nullable|date_format:Y-m-d|after_or_equal:today', 'start_time' => 'required|nullable|date_format:H:i:s', 'end_time' => 'required|nullable|date_format:H:i:s', 'setting' => 'required|in:0,1', + 'timezone' => 'required' ]); if ($validator->fails()) { return $this->validateResponse($validator->errors()); } $user = auth()->user(); - $now = Carbon::now()->format('Y-m-d'); - $perk = new Perk(); - $startDate = $request->start_date; - $endDate = $request->end_date; + + $timezone = $request->timezone; + + $startTime = $request->start_date . ' ' . $request->start_time; + $startTimeCarbon = Carbon::createFromFormat('Y-m-d H:i:s', $startTime, $timezone); + $startTimeCarbon->setTimezone('UTC'); + + $endTime = $request->end_date . ' ' . $request->end_time; + $endTimeCarbon = Carbon::createFromFormat('Y-m-d H:i:s', $endTime, $timezone); + $endTimeCarbon->setTimezone('UTC'); + $setting = $request->setting; - $visibility = 'hidden'; - $status = 'inactive'; - if ($startDate && $endDate && $startDate > $endDate) { + if ($startTimeCarbon->gte($endTimeCarbon)) { return $this->errorResponse('End date must greater than start date', Response::HTTP_BAD_REQUEST); } + $perk = new Perk(); $perk->user_id = $user->id; $perk->title = $request->title; $perk->content = $request->content; @@ -56,16 +66,16 @@ public function createPerk(Request $request) { $perk->end_date = $request->end_date; $perk->start_time = $request->start_time; $perk->end_time = $request->end_time; - $perk->setting = $request->setting; + $perk->setting = $setting; + $perk->timezone = $timezone; + $perk->time_begin = $startTimeCarbon; + $perk->time_end = $endTimeCarbon; $filenameWithExt = $request->file('image')->getClientOriginalName(); - //Get just filename $filename = pathinfo($filenameWithExt, PATHINFO_FILENAME); - // Get just ext $extension = $request->file('image')->getClientOriginalExtension(); - $filenamehash = md5(Str::random(10) . '_' . (string)time()); - // Filename to store + $filenamehash = md5(Str::random(10) . '_' . (string) time()); $fileNameToStore = $filenamehash . '.' . $extension; // S3 file upload @@ -77,39 +87,30 @@ public function createPerk(Request $request) { 'secret' => getenv('AWS_SECRET_ACCESS_KEY'), ], ]); - $s3result = $S3->putObject([ 'Bucket' => getenv('AWS_BUCKET'), 'Key' => 'client_uploads/' . $fileNameToStore, 'SourceFile' => $request->file('image') ]); - // $ObjectURL = 'https://'.getenv('AWS_BUCKET').'.s3.amazonaws.com/client_uploads/'.$fileNameToStore; $ObjectURL = $s3result['ObjectURL'] ?? getenv('SITE_URL') . '/not-found'; $perk->image = $ObjectURL; // check visibility and status + $now = Carbon::now('UTC'); + $visibility = 'hidden'; + $status = 'inactive'; if ($setting == 1) { - if ($startDate && $endDate && ($now >= $startDate && $now <= $endDate)) { - $visibility = 'visible'; - $status = 'active'; - } - if (!$startDate && !$endDate) { - $visibility = 'visible'; - $status = 'active'; - } - if ($endDate && $endDate >= $now) { - $visibility = 'visible'; - $status = 'active'; - } - if ($startDate && $startDate > $now) { - $visibility = 'hidden'; - $status = 'waiting'; - } - if ($startDate && $startDate <= $now) { - $visibility = 'visible'; - $status = 'active'; - } + if ($now >= $startTimeCarbon && $now <= $endTimeCarbon) { + $visibility = 'visible'; + $status = 'active'; + } else if ($now < $startTimeCarbon) { + $visibility = 'hidden'; + $status = 'waiting'; + } else if ($now > $endTimeCarbon) { + $visibility = 'hidden'; + $status = 'expired'; + } } else { $visibility = 'hidden'; $status = 'inactive'; @@ -117,30 +118,14 @@ public function createPerk(Request $request) { $perk->visibility = $visibility; $perk->status = $status; $perk->save(); - return $this->successResponse($perk); - } - public function getPerksAdmin(Request $request) - { - $limit = $request->limit ?? 50; - $sort_key = $request->sort_key ?? 'end_date'; - $sort_direction = $request->sort_direction ?? 'desc'; - if (isset($request->setting)) { - $perks = Perk::where('setting', $request->setting)->orderBy($sort_key, $sort_direction)->paginate($limit); - } else { - $perks = Perk::orderBy($sort_key, $sort_direction)->paginate($limit); - } - return $this->successResponse($perks); - } + if ($perk->visibility == 'visible' && $perk->status == 'active') { + PerkNotification::dispatch($perk)->onQueue('default_long'); + } - public function getPerkDetailAdmin($id) - { - $perk = Perk::where('id', $id)->first(); - if (!$perk) { - return $this->errorResponse('Not found perk', Response::HTTP_BAD_REQUEST); - } return $this->successResponse($perk); } + public function updatePerk(Request $request, $id) { $data = $request->all(); @@ -148,32 +133,43 @@ public function updatePerk(Request $request, $id) 'title' => 'nullable|string|max:70', 'content' => 'nullable', 'action_link' => 'nullable|url', - 'image' => 'nullable|mimes:jpeg,jpg,png,gif|max:100000', + // 'image' => 'nullable|mimes:pdf,jpeg,jpg,png,gif,txt,rtf|max:200000', + 'image' => 'nullable|mimes:pdf,jpeg,jpg,png,gif,txt,rtf|max:2048', 'start_date' => 'required|nullable', 'end_date' => 'required|nullable', 'start_time' => 'required|nullable|date_format:H:i:s', 'end_time' => 'required|nullable|date_format:H:i:s', 'setting' => 'nullable|in:0,1', + 'timezone' => 'required' ]); if ($validator->fails()) { return $this->validateResponse($validator->errors()); } $user = auth()->user(); - $now = Carbon::now()->format('Y-m-d'); + $perk = Perk::where('id', $id)->first(); if (!$perk) { return $this->errorResponse('Not found perk', Response::HTTP_BAD_REQUEST); } - $startDate = array_key_exists('start_date', $data) ? $request->start_date : $perk->start_date; - $endDate = array_key_exists('end_date', $data) ? $request->end_date : $perk->end_date; - $setting = isset($request->setting) ? $request->setting : $perk->setting; - $visibility = 'hidden'; - $status = 'inactive'; - if ($startDate && $endDate && $startDate > $endDate) { + $originalStatus = $perk->status; + $originalVisibility = $perk->visibility; + + $timezone = $request->timezone; + + $startTime = $request->start_date . ' ' . $request->start_time; + $startTimeCarbon = Carbon::createFromFormat('Y-m-d H:i:s', $startTime, $timezone); + $startTimeCarbon->setTimezone('UTC'); + + $endTime = $request->end_date . ' ' . $request->end_time; + $endTimeCarbon = Carbon::createFromFormat('Y-m-d H:i:s', $endTime, $timezone); + $endTimeCarbon->setTimezone('UTC'); + + if ($startTimeCarbon->gte($endTimeCarbon)) { return $this->errorResponse('End date must greater than start date', Response::HTTP_BAD_REQUEST); } + if ($request->title) { $perk->title = $request->title; } @@ -185,10 +181,14 @@ public function updatePerk(Request $request, $id) $perk->end_date = $request->end_date; $perk->start_time = $request->start_time; $perk->end_time = $request->end_time; - + $perk->timezone = $timezone; + $perk->time_begin = $startTimeCarbon; + $perk->time_end = $endTimeCarbon; + if (isset($request->setting)) { $perk->setting = $request->setting; } + if ($request->hasFile('image')) { $extension = $request->file('image')->getClientOriginalExtension(); $filenamehash = md5(Str::random(10) . '_' . (string)time()); @@ -216,31 +216,21 @@ public function updatePerk(Request $request, $id) } // check visibility and status - if ($setting == 1) { - if ($startDate && $endDate && ($now >= $startDate && $now <= $endDate)) { - $visibility = 'visible'; - $status = 'active'; - } - if (!$startDate && !$endDate) { - $visibility = 'visible'; - $status = 'active'; - } - if ($endDate && $endDate >= $now) { - $visibility = 'visible'; - $status = 'active'; - } - if ($endDate && $endDate < $now) { - $visibility = 'hidden'; - $status = 'expired'; - } - if ($startDate && $startDate > $now) { - $visibility = 'hidden'; - $status = 'waiting'; - } - if ($startDate && $startDate <= $now) { - $visibility = 'visible'; - $status = 'active'; - } + $visibility = 'hidden'; + $status = 'inactive'; + $setting = $perk->setting; + $now = Carbon::now('UTC'); + if ($setting == 1) { + if ($now >= $startTimeCarbon && $now <= $endTimeCarbon) { + $visibility = 'visible'; + $status = 'active'; + } else if ($now < $startTimeCarbon) { + $visibility = 'hidden'; + $status = 'waiting'; + } else if ($now > $endTimeCarbon) { + $visibility = 'hidden'; + $status = 'expired'; + } } else { $visibility = 'hidden'; $status = 'inactive'; @@ -248,6 +238,37 @@ public function updatePerk(Request $request, $id) $perk->visibility = $visibility; $perk->status = $status; $perk->save(); + + if ( + $perk->visibility == 'visible' && + $perk->status == 'active' && + ($perk->visibility != $originalVisibility || $perk->status != $originalStatus) + ) { + PerkNotification::dispatch($perk)->onQueue('default_long'); + } + + return $this->successResponse($perk); + } + + public function getPerksAdmin(Request $request) + { + $limit = $request->limit ?? 50; + $sort_key = $request->sort_key ?? 'end_date'; + $sort_direction = $request->sort_direction ?? 'desc'; + if (isset($request->setting)) { + $perks = Perk::where('setting', $request->setting)->orderBy($sort_key, $sort_direction)->paginate($limit); + } else { + $perks = Perk::orderBy($sort_key, $sort_direction)->paginate($limit); + } + return $this->successResponse($perks); + } + + public function getPerkDetailAdmin($id) + { + $perk = Perk::where('id', $id)->first(); + if (!$perk) { + return $this->errorResponse('Not found perk', Response::HTTP_BAD_REQUEST); + } return $this->successResponse($perk); } diff --git a/app/Http/Controllers/Api/V1/UserController.php b/app/Http/Controllers/Api/V1/UserController.php index 75a968ee..af98a02b 100644 --- a/app/Http/Controllers/Api/V1/UserController.php +++ b/app/Http/Controllers/Api/V1/UserController.php @@ -9,7 +9,6 @@ use App\Http\Requests\Api\AddOwnerNodeRequest; use App\Http\Requests\Api\ChangeEmailRequest; -use App\Http\Requests\Api\ChangePasswordRequest; use App\Http\Requests\Api\ResendEmailRequest; use App\Http\Requests\Api\SubmitKYCRequest; use App\Http\Requests\Api\SubmitPublicAddressRequest; @@ -40,6 +39,10 @@ use App\Models\VerifyUser; use App\Models\Vote; use App\Models\VoteResult; +use App\Models\Setting; +use App\Models\AllNodeData2; +use App\Models\Upgrade; +use App\Models\UpgradeUser; use App\Repositories\OwnerNodeRepository; use App\Repositories\ProfileRepository; @@ -77,13 +80,13 @@ class UserController extends Controller private $verifyUserRepo; private $profileRepo; private $ownerNodeRepo; - public $failed_verification_response; + public $failed_verification_response; public function __construct( - UserRepository $userRepo, + UserRepository $userRepo, VerifyUserRepository $verifyUserRepo, - ProfileRepository $profileRepo, - OwnerNodeRepository $ownerNodeRepo + ProfileRepository $profileRepo, + OwnerNodeRepository $ownerNodeRepo ) { $this->userRepo = $userRepo; $this->verifyUserRepo = $verifyUserRepo; @@ -92,39 +95,390 @@ public function __construct( $this->failed_verification_response = 'Failed verification'; } - public function getMemberCountInfo() { - $data = [ - 'total' => 0, - 'verified' => 0, + public function getUserDashboard() { + $user = auth()->user(); + $user_id = $user->id ?? 0; + + $settings = Helper::getSettings(); + $current_era_id = (int) ($settings['current_era_id'] ?? 0); + + $return = [ + 'node_rank' => 0, + 'node_rank_total' => 0, + 'total_stake' => 0, + 'total_self_stake' => 0, + 'total_delegators' => 0, + 'uptime' => 0, + 'eras_active' => 0, + 'eras_since_bad_mark' => $current_era_id, + 'total_bad_marks' => 0, + 'update_responsiveness' => 100, + 'peers' => 0, + 'total_members' => 0, + 'verified_members' => 0, + 'association_members' => Helper::getActiveMembers(), + 'ranking' => [] ]; - $data['total'] = User::count(); - $data['verified'] = User::join('profile', 'profile.user_id', '=', 'users.id') - ->where('profile.status', 'approved') - ->whereNotNull('users.public_address_node') - ->get() - ->count(); - return $this->successResponse($data); + // get verified members count + $verified_members = DB::select(" + SELECT count(a.id) as totalCount + FROM users AS a + JOIN profile AS b + ON a.id = b.user_id + WHERE b.status = 'approved' + "); + $return['verified_members'] = $verified_members[0]->totalCount ?? 0; + + // get total members count + $total_members = DB::select(" + SELECT count(id) as totalCount + FROM users + WHERE role = 'member' + "); + $return['total_members'] = $total_members[0]->totalCount ?? 0; + + $rankingData = Helper::getRanking($current_era_id); + + $return['ranking'] = $rankingData['ranking']; + $return['node_rank_total'] = $rankingData['node_rank_total']; + + // parse node addresses + $addresses = DB::select(" + SELECT + a.public_key, + a.uptime, + a.bid_delegators_count AS delegators, + a.port8888_peers AS peers, + a.bid_self_staked_amount, a.bid_total_staked_amount + FROM all_node_data2 AS a + JOIN user_addresses AS b + ON a.public_key = b.public_address_node + JOIN users AS c + ON b.user_id = c.id + WHERE a.era_id = $current_era_id + AND b.user_id = $user_id + "); + if (!$addresses) $addresses = []; + + // for each address belonging to a user + foreach ($addresses as $address) { + $p = $address->public_key ?? ''; + + $baseObject = new \stdClass(); + $baseObject->uptime = (float) ($address->uptime ?? 0); + + $badMarkValues = Helper::calculateVariables('bad_marks_info', $p, $settings); + $total_bad_marks = (int) ($badMarkValues['total_bad_marks'] ?? 0); + $eras_since_bad_mark = (int) ($badMarkValues['eras_since_bad_mark'] ?? $current_era_id); + $return['total_bad_marks'] += $total_bad_marks; + if ($eras_since_bad_mark < $return['eras_since_bad_mark']) { + $return['eras_since_bad_mark'] = $eras_since_bad_mark; + } + + $min_era_id = Helper::calculateVariables('min_era', $p, $settings); + if ($current_era_id - $min_era_id > $return['eras_active']) { + $return['eras_active'] = $current_era_id - $min_era_id; + } + + $historical_performance = Helper::calculateUptime($baseObject, $p, $settings); + + if ( + array_key_exists($p, $return['ranking']) && + ($return['node_rank'] == 0 || $return['ranking'][$p] < $return['node_rank']) + ) { + $return['node_rank'] = $return['ranking'][$p]; + } + + $return['total_stake'] += (int) ($address->bid_total_staked_amount ?? 0); + $return['total_self_stake'] += (int) ($address->bid_self_staked_amount ?? 0); + $return['total_delegators'] += (int) ($address->delegators ?? 0); + $return['peers'] += (int) ($address->peers ?? 0); + $return['uptime'] += $historical_performance; + } + + $addresses_count = count($addresses); + if (!$addresses_count) $addresses_count = 1; + + $return['uptime'] = round((float) ($return['uptime'] / $addresses_count), 2); + + unset($return['ranking']); + + return $this->successResponse($return); } - // Get Verified Members - public function getVerifiedMembers(Request $request) { - $data = []; - $limit = $request->limit ?? 50; + public function getMembershipPage() { + $user = auth()->user()->load(['profile']); + $user_id = $user->id ?? 0; + + $settings = Helper::getSettings(); + $current_era_id = (int) ($settings['current_era_id'] ?? 0); + + $return = [ + 'node_status' => $user->node_status ?? '', + 'kyc_status' => 'Not Verified', + 'uptime' => [], + 'avg_uptime' => 0, + 'total_eras' => 0, + 'eras_since_bad_mark' => $current_era_id, + 'total_bad_marks' => 0, + 'update_responsiveness' => 100, + 'peers' => 0 + ]; + if (isset($user->profile) && $user->profile->status == 'approved') { + $return['kyc_status'] = 'Verified'; + } + + $addresses = DB::select(" + SELECT + a.public_key, a.uptime, + a.port8888_peers AS peers, + a.bid_inactive, a.in_current_era, + c.kyc_verified_at AS kyc_status + FROM all_node_data2 AS a + JOIN user_addresses AS b + ON a.public_key = b.public_address_node + LEFT JOIN users AS c + ON b.user_id = c.id + WHERE a.era_id = $current_era_id + AND b.user_id = $user_id + "); + if (!$addresses) $addresses = []; + + foreach ($addresses as $address) { + $p = $address->public_key ?? ''; + + $baseObject = new \stdClass(); + $baseObject->uptime = (float) ($address->uptime ?? 0); + + $badMarkValues = Helper::calculateVariables('bad_marks_info', $p, $settings); + $total_bad_marks = (int) ($badMarkValues['total_bad_marks'] ?? 0); + $eras_since_bad_mark = (int) ($badMarkValues['eras_since_bad_mark'] ?? $current_era_id); + $return['total_bad_marks'] += $total_bad_marks; + if ($eras_since_bad_mark < $return['eras_since_bad_mark']) { + $return['eras_since_bad_mark'] = $eras_since_bad_mark; + } + + $min_era_id = Helper::calculateVariables('min_era', $p, $settings); + if ($current_era_id - $min_era_id > $return['total_eras']) { + $return['total_eras'] = $current_era_id - $min_era_id; + } + + $historical_performance = Helper::calculateUptime($baseObject, $p, $settings); + + $return['peers'] += (int) ($address->peers ?? 0); + $return['uptime'][$p] = $historical_performance; + $return['avg_uptime'] += $historical_performance; + } + + $addresses_count = count($addresses); + $addresses_count = $addresses_count ? $addresses_count : 1; + $return['avg_uptime'] = round((float) ($return['avg_uptime'] / $addresses_count), 2); + + return $this->successResponse($return); + } + + public function getNodesPage() { $user = auth()->user(); + $user_id = $user->id ?? 0; - $data = User::select([ - 'users.id', - 'users.pseudonym', - 'users.public_address_node', - 'users.node_status', - 'profile.extra_status', - ]) - ->join('profile', 'profile.user_id', '=', 'users.id') - ->where('profile.status', 'approved') - ->whereNotNull('users.public_address_node') - ->paginate($limit); - return $this->successResponse($data); + $nodeHelper = new NodeHelper(); + + $settings = Helper::getSettings(); + $current_era_id = (int) ($settings['current_era_id'] ?? 0); + + $return = [ + 'mbs' => 0, + 'ranking' => [], + 'addresses' => [] + ]; + + $rankingData = Helper::getRanking($current_era_id); + + $return['ranking'] = $rankingData['ranking']; + + $addresses = DB::select(" + SELECT + a.public_key, a.bid_delegators_count, + a.bid_total_staked_amount, a.bid_self_staked_amount, + a.uptime, a.bid_inactive, a.in_current_era, + a.port8888_peers AS peers + FROM all_node_data2 AS a + JOIN user_addresses AS b + ON a.public_key = b.public_address_node + JOIN users AS c + ON b.user_id = c.id + WHERE a.era_id = $current_era_id + AND b.user_id = $user_id + "); + if (!$addresses) $addresses = []; + + // fetch MBS + $mbs = DB::select(" + SELECT mbs + FROM mbs + WHERE era_id = $current_era_id + "); + $mbs = $mbs[0]->mbs ?? 0; + + // for each member's node address + foreach ($addresses as $address) { + $p = $address->public_key ?? ''; + + $baseObject = new \stdClass(); + $baseObject->uptime = (float) ($address->uptime ?? 0); + $baseObject->mbs = $mbs; + + $badMarkValues = Helper::calculateVariables('bad_marks_info', $p, $settings); + $total_bad_marks = (int) ($badMarkValues['total_bad_marks'] ?? 0); + $eras_since_bad_mark = (int) ($badMarkValues['eras_since_bad_mark'] ?? $current_era_id); + + $min_era_id = Helper::calculateVariables('min_era', $p, $settings); + $total_eras = $current_era_id - $min_era_id; + + $historical_performance = Helper::calculateUptime($baseObject, $p, $settings); + + $one_day_ago = Carbon::now('UTC')->subHours(24); + $temp = DB::select(" + SELECT bid_self_staked_amount + FROM all_node_data2 + WHERE public_key = '$p' + AND created_at < '$one_day_ago' + ORDER BY era_id DESC + LIMIT 1 + "); + if (!$temp) $temp = []; + $daily_earning = (float) $address->bid_self_staked_amount - (float) ($temp[0]->bid_self_staked_amount ?? 0); + $daily_earning = $daily_earning < 0 ? 0 : $daily_earning; + + $earning_day = $nodeHelper->getValidatorRewards($p, 'day'); + $earning_week = $nodeHelper->getValidatorRewards($p, 'week'); + $earning_month = $nodeHelper->getValidatorRewards($p, 'month'); + $earning_year = $nodeHelper->getValidatorRewards($p, 'year'); + + $return['addresses'][$p] = [ + 'stake_amount' => $address->bid_total_staked_amount, + 'delegators' => $address->bid_delegators_count, + 'uptime' => $historical_performance, + 'update_responsiveness' => 100, + 'peers' => (int) ($address->peers ?? 0), + 'daily_earning' => $daily_earning, + 'total_eras' => $total_eras, + 'eras_since_bad_mark' => $eras_since_bad_mark, + 'total_bad_marks' => $total_bad_marks, + 'validator_rewards' => [ + 'day' => $earning_day, + 'week' => $earning_week, + 'month' => $earning_month, + 'year' => $earning_year + ] + ]; + } + + $return['mbs'] = $mbs; + + return $this->successResponse($return); + } + + public function getMyEras() { + $user = auth()->user(); + $user_id = $user->id ?? 0; + + $settings = Helper::getSettings(); + $current_era_id = (int) ($settings['current_era_id'] ?? 0); + + // define return object + $return = [ + 'addresses' => [], + 'eras' => [] + ]; + + // get addresses data + $addresses = DB::select(" + SELECT + a.public_key, a.uptime + FROM all_node_data2 AS a + JOIN user_addresses AS b + ON a.public_key = b.public_address_node + JOIN users AS c + ON b.user_id = c.id + WHERE a.era_id = $current_era_id + AND b.user_id = $user_id + "); + if (!$addresses) $addresses = []; + + $uptime_calc_size = isset($settings['uptime_calc_size']) ? (int) $settings['uptime_calc_size'] : 1; + + // for each member's node address + foreach ($addresses as $address) { + $p = $address->public_key ?? ''; + + $baseObject = new \stdClass(); + $baseObject->uptime = (float) ($address->uptime ?? 0); + + $badMarkValues = Helper::calculateVariables('bad_marks_info', $p, $settings); + $total_bad_marks = (int) ($badMarkValues['total_bad_marks'] ?? 0); + $eras_since_bad_mark = (int) ($badMarkValues['eras_since_bad_mark'] ?? $current_era_id); + + $min_era_id = Helper::calculateVariables('min_era', $p, $settings); + $eras_active = $current_era_id - $min_era_id; + + $historical_performance = Helper::calculateUptime($baseObject, $p, $settings); + + $return['addresses'][$p] = [ + 'uptime' => $historical_performance, + 'eras_active' => $eras_active, + 'eras_since_bad_mark' => $eras_since_bad_mark, + 'total_bad_marks' => $total_bad_marks + ]; + } + + // get eras table data + $era_minus_360 = $current_era_id - $uptime_calc_size; + if ($era_minus_360 < 1) { + $era_minus_360 = 1; + } + + $eras = DB::select(" + SELECT + a.public_key, a.era_id, a.created_at, + a.in_current_era, a.in_auction, + a.bid_inactive, a.uptime + FROM all_node_data2 AS a + JOIN user_addresses + ON a.public_key = user_addresses.public_address_node + JOIN users + ON user_addresses.user_id = users.id + WHERE users.id = $user_id + AND era_id > $era_minus_360 + ORDER BY a.era_id DESC + "); + if (!$eras) $eras = []; + + $sorted_eras = []; + + // for each node address's era + foreach ($eras as $era) { + $era_id = $era->era_id ?? 0; + $era_start_time = $era->created_at ?? ''; + $public_key = $era->public_key; + + if (!isset($sorted_eras[$era_id])) { + $sorted_eras[$era_id] = [ + 'era_start_time' => $era_start_time, + 'addresses' => [] + ]; + } + + $sorted_eras[$era_id]['addresses'][$public_key] = [ + 'in_pool' => $era->in_auction, + 'rewards' => $era->uptime ?? 0 + ]; + } + + $return['eras'] = $sorted_eras; + + return $this->successResponse($return); } // Shuftipro Webhook @@ -152,12 +506,12 @@ public function updateShuftiproStatus() { if ($user) { $user_id = $user->id; $profile = Profile::where('user_id', $user_id)->first(); - + if ($profile) { $profile->status = null; $profile->save(); } - + Shuftipro::where('user_id', $user->id)->delete(); ShuftiproTemp::where('user_id', $user->id)->delete(); } @@ -167,8 +521,9 @@ public function updateShuftiproStatus() { } else { $events = [ 'verification.accepted', - 'verification.declined', + 'verification.declined' ]; + if (isset($data['event']) && in_array($data['event'], $events)) { $user = User::find($recordTemp->user_id); @@ -194,11 +549,15 @@ public function updateShuftiproStatus() { public function changeEmail(ChangeEmailRequest $request) { + return $this->successResponse( + ['message' => __('Email changes are disabled')] + ); + try { DB::beginTransaction(); $user = auth()->user(); $user->update(['email' => $request->email, 'email_verified_at' => null]); - $code = generateString(7); + $code = Helper::generateString(7); $userVerify = $this->verifyUserRepo->updateOrCreate( [ 'email' => $request->email, @@ -206,9 +565,10 @@ public function changeEmail(ChangeEmailRequest $request) ], [ 'code' => $code, - 'created_at' => now() + 'created_at' => Carbon::now('UTC') ] ); + if ($userVerify) Mail::to($request->email)->send(new UserVerifyMail($code)); DB::commit(); return $this->metaSuccess(); @@ -216,29 +576,68 @@ public function changeEmail(ChangeEmailRequest $request) return $this->errorResponse(__('api.error.internal_error'), Response::HTTP_INTERNAL_SERVER_ERROR); } } - - public function changePassword(ChangePasswordRequest $request) - { - $user = auth()->user(); - if (Hash::check($request->new_password, $user->password)) - return $this->errorResponse(__('api.error.not_same_current_password'), Response::HTTP_BAD_REQUEST); - $newPassword = bcrypt($request->new_password); - $user->update(['password' => $newPassword]); - return $this->metaSuccess(); - } public function getProfile() { $user = auth()->user()->load(['profile', 'pagePermissions', 'permissions', 'shuftipro', 'shuftiproTemp']); Helper::getAccountInfoStandard($user); - $user->metric = Helper::getNodeInfo($user); + $user->globalSettings = Helper::getSettings(); + $lastUpgrade = Upgrade::orderBy('id', 'desc')->limit(1)->first(); + $now = Carbon::now('UTC'); + if ($lastUpgrade) { + $lastUpgrade->time_passed = !!($now >= $lastUpgrade->activation_datetime); + $user->lastUpgrade = $lastUpgrade; + $reply = UpgradeUser::where('upgrade_id', $lastUpgrade->id) + ->where('user_id', $user->id) + ->first(); + if ($reply) { + $user->lastUpgradeReply = $reply; + } + } + $ownReply = UpgradeUser::where('user_id', $user->id) + ->orderBy('created_at', 'desc') + ->orderBy('upgrade_id', 'desc') + ->limit(1) + ->first(); + if ($ownReply) { + $lastOwnUpgrade = Upgrade::find($ownReply->upgrade_id); + if ($lastOwnUpgrade) { + $user->lastOwnUpgrade = $lastOwnUpgrade; + $user->lastOwnUpgradeReply = $ownReply; + } + } return $this->successResponse($user); } - public function logout() - { - auth()->user()->token()->revoke(); - return $this->metaSuccess(); + public function completeUpgrade(Request $request) { + $user_id = auth()->user()->id; + $validator = Validator::make($request->all(), [ + 'upgrade_id' => 'required|integer' + ]); + if ($validator->fails()) { + return $this->validateResponse($validator->errors()); + } + $upgrade_id = (int) $request->upgrade_id; + + $upgrade = Upgrade::find($upgrade_id); + $now = Carbon::now('UTC'); + if (!$upgrade || $upgrade->activation_datetime <= $now) { + return $this->errorResponse(__('The Upgrade is invalid'), Response::HTTP_BAD_REQUEST); + } + + $upgradeReply = UpgradeUser::where('upgrade_id', $upgrade_id) + ->where('user_id', $user_id) + ->first(); + if ($upgradeReply) { + return $this->errorResponse(__('The Upgrade is invalid'), Response::HTTP_BAD_REQUEST); + } + + $upgradeReply = new UpgradeUser; + $upgradeReply->upgrade_id = $upgrade_id; + $upgradeReply->user_id = $user_id; + $upgradeReply->save(); + + return $this->metaSuccess(); } public function uploadLetter(Request $request) @@ -246,7 +645,7 @@ public function uploadLetter(Request $request) try { // Validator $validator = Validator::make($request->all(), [ - 'file' => 'required|mimes:pdf,docx,doc,txt,rtf|max:20000', + 'file' => 'required|mimes:pdf,jpeg,jpg,png,txt,rtf|max:2048' ]); if ($validator->fails()) { @@ -345,41 +744,71 @@ public function submitPublicAddress(SubmitPublicAddressRequest $request) $user = auth()->user(); $address = strtolower($request->public_address); $public_address = strtolower($address); - $public_address_temp = (new ChecksumValidator())->do($address); + if (!$public_address_temp) { return $this->errorResponse(__('The validator ID is invalid'), Response::HTTP_BAD_REQUEST); } - + $correct_checksum = (int) (new ChecksumValidator($public_address_temp))->do(); + if (!$correct_checksum) { - return $this->errorResponse(__('The validator ID is invalid'), Response::HTTP_BAD_REQUEST); + return $this->errorResponse( + __('The validator ID is invalid'), + Response::HTTP_BAD_REQUEST + ); } - + // User Check $tempUser = User::where('public_address_node', $public_address)->first(); - if ($tempUser && $tempUser->id != $user->id && $tempUser->node_verified_at) { - return $this->errorResponse(__('The validator ID you specified is already associated with an Association member'), Response::HTTP_BAD_REQUEST); + + if ( + $tempUser && + $tempUser->id != $user->id && + $tempUser->node_verified_at + ) { + return $this->errorResponse( + __('The validator ID you specified is already associated with an Association member'), + Response::HTTP_BAD_REQUEST + ); } // User Address Check $tempUserAddress = UserAddress::where('public_address_node', $public_address)->first(); - if ($tempUserAddress && $tempUserAddress->user_id != $user->id && $tempUserAddress->node_verified_at) { - return $this->errorResponse(__('The validator ID you specified is already associated with an Association member'), Response::HTTP_BAD_REQUEST); + + if ( + $tempUserAddress && + $tempUserAddress->user_id != $user->id && + $tempUserAddress->node_verified_at + ) { + return $this->errorResponse( + __('The validator ID you specified is already associated with an Association member'), + Response::HTTP_BAD_REQUEST + ); } // Pool Check - $nodeHelper = new NodeHelper(); - $addresses = $nodeHelper->getValidAddresses(); - if (!in_array($public_address, $addresses)) { - return $this->errorResponse(__('The validator ID specified could not be found in the Casper validator pool'), Response::HTTP_BAD_REQUEST); + if (!Helper::checkAddressValidity($public_address)) { + return $this->errorResponse( + __('The validator ID specified could not be found in the Casper validator pool'), + Response::HTTP_BAD_REQUEST + ); } // Remove Other User's Same Address - UserAddress::where('public_address_node', $public_address)->where('user_id', '!=', $user->id)->whereNull('node_verified_at')->delete(); - User::where('public_address_node', $public_address)->where('id', '!=', $user->id)->whereNull('node_verified_at')->update(['public_address_node' => null]); + UserAddress::where('public_address_node', $public_address) + ->where('user_id', '!=', $user->id) + ->whereNull('node_verified_at') + ->delete(); + User::where('public_address_node', $public_address) + ->where('id', '!=', $user->id) + ->whereNull('node_verified_at') + ->update(['public_address_node' => null]); - if (!$tempUserAddress || $tempUserAddress->user_id != $user->id) { + if ( + !$tempUserAddress || + $tempUserAddress->user_id != $user->id + ) { $userAddress = new UserAddress; $userAddress->user_id = $user->id; $userAddress->public_address_node = $public_address; @@ -397,36 +826,47 @@ public function submitPublicAddress(SubmitPublicAddressRequest $request) public function checkValidatorAddress(SubmitPublicAddressRequest $request) { $address = strtolower($request->public_address); - $public_address_temp = (new ChecksumValidator())->do($address); $public_address = strtolower($address); if (!$public_address_temp) { - return $this->successResponse(['message' => __('The validator ID is invalid')]); + return $this->successResponse( + ['message' => __('The validator ID is invalid')] + ); } $correct_checksum = (int) (new ChecksumValidator($public_address_temp))->do(); + if (!$correct_checksum) { - return $this->successResponse(['message' => __('The validator ID is invalid')]); + return $this->successResponse( + ['message' => __('The validator ID is invalid')] + ); } // User Check $tempUser = User::where('public_address_node', $public_address)->first(); + if ($tempUser && $tempUser->node_verified_at) { - return $this->successResponse(['message' => __('The validator ID you specified is already associated with an Association member')]); + return $this->successResponse( + ['message' => __('The validator ID you specified is already associated with an Association member')] + ); } // User Address Check $tempUserAddress = UserAddress::where('public_address_node', $public_address)->first(); + if ($tempUserAddress && $tempUserAddress->node_verified_at) { - return $this->successResponse(['message' => __('The validator ID you specified is already associated with an Association member')]); + return $this->successResponse( + ['message' => __('The validator ID you specified is already associated with an Association member')] + ); } - $nodeHelper = new NodeHelper(); - $addresses = $nodeHelper->getValidAddresses(); - if (!in_array($public_address, $addresses)) { - return $this->successResponse(['message' => __('The validator ID specified could not be found in the Casper validator pool')]); - } + if (!Helper::checkAddressValidity($public_address)) { + return $this->successResponse( + ['message' => __('The validator ID specified could not be found in the Casper validator pool')] + ); + } + return $this->metaSuccess(); } @@ -434,34 +874,50 @@ public function checkPublicAddress(SubmitPublicAddressRequest $request) { $address = strtolower($request->public_address); $public_address = strtolower($address); - $public_address_temp = (new ChecksumValidator())->do($address); + if (!$public_address_temp) { - return $this->errorResponse(__('The validator ID is invalid'), Response::HTTP_BAD_REQUEST); + return $this->errorResponse( + __('The validator ID is invalid'), + Response::HTTP_BAD_REQUEST + ); } $correct_checksum = (int) (new ChecksumValidator($public_address_temp))->do(); + if (!$correct_checksum) { - return $this->errorResponse(__('The validator ID is invalid'), Response::HTTP_BAD_REQUEST); + return $this->errorResponse( + __('The validator ID is invalid'), + Response::HTTP_BAD_REQUEST + ); } // User Check $tempUser = User::where('public_address_node', $public_address)->first(); + if ($tempUser && $tempUser->node_verified_at) { - return $this->errorResponse(__('The validator ID you specified is already associated with an Association member'), Response::HTTP_BAD_REQUEST); + return $this->errorResponse( + __('The validator ID you specified is already associated with an Association member'), + Response::HTTP_BAD_REQUEST + ); } // User Address Check $tempUserAddress = UserAddress::where('public_address_node', $public_address)->first(); + if ($tempUserAddress && $tempUserAddress->node_verified_at) { - return $this->errorResponse(__('The validator ID you specified is already associated with an Association member'), Response::HTTP_BAD_REQUEST); + return $this->errorResponse( + __('The validator ID you specified is already associated with an Association member'), + Response::HTTP_BAD_REQUEST + ); } // Pool Check - $nodeHelper = new NodeHelper(); - $addresses = $nodeHelper->getValidAddresses(); - if (!in_array($public_address, $addresses)) { - return $this->errorResponse(__('The validator ID specified could not be found in the Casper validator pool'), Response::HTTP_BAD_REQUEST); + if (!Helper::checkAddressValidity($public_address)) { + return $this->errorResponse( + __('The validator ID specified could not be found in the Casper validator pool'), + Response::HTTP_BAD_REQUEST + ); } return $this->metaSuccess(); @@ -469,11 +925,12 @@ public function checkPublicAddress(SubmitPublicAddressRequest $request) public function getMessageContent() { - $user = auth()->user(); + $user = auth()->user(); $timestamp = date('d/m/Y'); - $message = "Please use the Casper Signature python tool to sign this message! " . $timestamp; + $message = "Please use the Casper Signature python tool to sign this message! " . $timestamp; $user->update(['message_content' => $message]); - $filename = 'message.txt'; + $filename = 'message.txt'; + return response()->streamDownload(function () use ($message) { echo $message; }, $filename); @@ -482,24 +939,37 @@ public function getMessageContent() public function verifyFileCasperSigner2(VerifyFileCasperSignerRequest $request) { try { - $casperSigVerify = new CasperSigVerify(); - $user = auth()->user(); - $message = $user->message_content; + $casperSigVerify = new CasperSigVerify(); + $user = auth()->user(); + $message = $user->message_content; $public_validator_key = strtolower($request->address); - $userRecord = User::where('public_address_node', $public_validator_key)->first(); - $userAddress = UserAddress::where('public_address_node', $public_validator_key)->first(); + $userRecord = User::where( + 'public_address_node', + $public_validator_key + )->first(); + + $userAddress = UserAddress::where( + 'public_address_node', + $public_validator_key + )->first(); if ($userRecord && $userRecord->node_verified_at) { - return $this->errorResponse(__($this->failed_verification_response), Response::HTTP_BAD_REQUEST); + return $this->errorResponse( + __($this->failed_verification_response), + Response::HTTP_BAD_REQUEST + ); } if ($userAddress && $userAddress->node_verified_at) { - return $this->errorResponse(__($this->failed_verification_response), Response::HTTP_BAD_REQUEST); + return $this->errorResponse( + __($this->failed_verification_response), + Response::HTTP_BAD_REQUEST + ); } - $file = $request->file; - $name = $file->getClientOriginalName(); + $file = $request->file; + $name = $file->getClientOriginalName(); $hexstring = $file->get(); if ($hexstring && $name == 'signature') { @@ -513,32 +983,47 @@ public function verifyFileCasperSigner2(VerifyFileCasperSignerRequest $request) $filenamehash = md5(Str::random(10) . '_' . (string)time()); $S3 = new S3Client([ - 'version' => 'latest', - 'region' => getenv('AWS_DEFAULT_REGION'), + 'version' => 'latest', + 'region' => getenv('AWS_DEFAULT_REGION'), 'credentials' => [ - 'key' => getenv('AWS_ACCESS_KEY_ID'), - 'secret' => getenv('AWS_SECRET_ACCESS_KEY'), + 'key' => getenv('AWS_ACCESS_KEY_ID'), + 'secret' => getenv('AWS_SECRET_ACCESS_KEY'), ], ]); $s3result = $S3->putObject([ - 'Bucket' => getenv('AWS_BUCKET'), - 'Key' => 'signatures/' . $filenamehash, - 'SourceFile' => $request->file('file') + 'Bucket' => getenv('AWS_BUCKET'), + 'Key' => 'signatures/' . $filenamehash, + 'SourceFile' => $request->file('file') ]); $ObjectURL = $s3result['ObjectURL'] ?? getenv('SITE_URL').'/not-found'; // Remove Other User's Same Address - UserAddress::where('public_address_node', $public_validator_key)->where('user_id', '!=', $user->id)->whereNull('node_verified_at')->delete(); - User::where('public_address_node', $public_validator_key)->where('id', '!=', $user->id)->whereNull('node_verified_at')->update(['public_address_node' => null]); - - $userAddress = UserAddress::where('public_address_node', $public_validator_key)->where('user_id', $user->id)->first(); - if (!$userAddress) $userAddress = new UserAddress; - $userAddress->user_id = $user->id; + UserAddress::where('public_address_node', $public_validator_key) + ->where('user_id', '!=', $user->id) + ->whereNull('node_verified_at') + ->delete(); + + User::where('public_address_node', $public_validator_key) + ->where('id', '!=', $user->id) + ->whereNull('node_verified_at') + ->update(['public_address_node' => null]); + + $userAddress = UserAddress::where( + 'public_address_node', + $public_validator_key) + ->where('user_id', $user->id) + ->first(); + + if (!$userAddress) { + $userAddress = new UserAddress; + } + + $userAddress->user_id = $user->id; $userAddress->public_address_node = $public_validator_key; - $userAddress->signed_file = $ObjectURL; - $userAddress->node_verified_at = now(); + $userAddress->signed_file = $ObjectURL; + $userAddress->node_verified_at = Carbon::now('UTC'); $userAddress->save(); $emailerData = EmailerHelper::getEmailerData(); @@ -552,32 +1037,50 @@ public function verifyFileCasperSigner2(VerifyFileCasperSignerRequest $request) ); return $this->metaSuccess(); } else { - return $this->errorResponse(__($this->failed_verification_response), Response::HTTP_BAD_REQUEST); + return $this->errorResponse( + __($this->failed_verification_response), + Response::HTTP_BAD_REQUEST + ); } } - return $this->errorResponse(__($this->failed_verification_response), Response::HTTP_BAD_REQUEST); + return $this->errorResponse( + __($this->failed_verification_response), + Response::HTTP_BAD_REQUEST + ); } catch (\Exception $ex) { - return $this->errorResponse(__($this->failed_verification_response), Response::HTTP_BAD_REQUEST, $ex->getMessage()); + return $this->errorResponse( + __($this->failed_verification_response), + Response::HTTP_BAD_REQUEST, + $ex->getMessage() + ); } } public function verifyFileCasperSigner(VerifyFileCasperSignerRequest $request) { try { - $casperSigVerify = new CasperSigVerify(); - $user = auth()->user(); - $message = $user->message_content; + $casperSigVerify = new CasperSigVerify(); + $user = auth()->user(); + $message = $user->message_content; $public_validator_key = strtolower($request->address); - $userRecord = User::where('id', $user->id)->where('public_address_node', $public_validator_key)->first(); - $userAddress = UserAddress::where('user_id', $user->id)->where('public_address_node', $public_validator_key)->first(); + $userRecord = User::where('id', $user->id) + ->where('public_address_node', $public_validator_key) + ->first(); + + $userAddress = UserAddress::where('user_id', $user->id) + ->where('public_address_node', $public_validator_key) + ->first(); + if (!$userRecord || !$userAddress) { - return $this->errorResponse(__($this->failed_verification_response), Response::HTTP_BAD_REQUEST); + return $this->errorResponse( + __($this->failed_verification_response), + Response::HTTP_BAD_REQUEST + ); } - $file = $request->file; - - $name = $file->getClientOriginalName(); + $file = $request->file; + $name = $file->getClientOriginalName(); $hexstring = $file->get(); if ($hexstring && $name == 'signature') { @@ -586,130 +1089,119 @@ public function verifyFileCasperSigner(VerifyFileCasperSignerRequest $request) $public_validator_key, $message ); + if ($verified) { $filenamehash = md5(Str::random(10) . '_' . (string)time()); // S3 file upload $S3 = new S3Client([ - 'version' => 'latest', - 'region' => getenv('AWS_DEFAULT_REGION'), + 'version' => 'latest', + 'region' => getenv('AWS_DEFAULT_REGION'), 'credentials' => [ - 'key' => getenv('AWS_ACCESS_KEY_ID'), - 'secret' => getenv('AWS_SECRET_ACCESS_KEY'), + 'key' => getenv('AWS_ACCESS_KEY_ID'), + 'secret' => getenv('AWS_SECRET_ACCESS_KEY'), ], ]); $s3result = $S3->putObject([ - 'Bucket' => getenv('AWS_BUCKET'), - 'Key' => 'signatures/' . $filenamehash, - 'SourceFile' => $request->file('file') + 'Bucket' => getenv('AWS_BUCKET'), + 'Key' => 'signatures/' . $filenamehash, + 'SourceFile' => $request->file('file') ]); $ObjectURL = $s3result['ObjectURL'] ?? getenv('SITE_URL').'/not-found'; - - $user->signed_file = $ObjectURL; - $user->has_verified_address = 1; - $user->node_verified_at = now(); + + $user->signed_file = $ObjectURL; + $user->has_verified_address = 1; + $user->node_verified_at = Carbon::now('UTC'); $user->save(); - $userAddress->signed_file = $ObjectURL; - $userAddress->node_verified_at = now(); + $userAddress->signed_file = $ObjectURL; + $userAddress->node_verified_at = Carbon::now('UTC'); $userAddress->save(); $emailerData = EmailerHelper::getEmailerData(); - EmailerHelper::triggerUserEmail($user->email, 'Your Node is Verified', $emailerData, $user); - if ($user->letter_verified_at && $user->signature_request_id && $user->node_verified_at) - EmailerHelper::triggerUserEmail($user->email, 'Congratulations', $emailerData, $user); + EmailerHelper::triggerUserEmail( + $user->email, + 'Your Node is Verified', + $emailerData, + $user + ); + + if ( + $user->letter_verified_at && + $user->signature_request_id && + $user->node_verified_at + ) { + EmailerHelper::triggerUserEmail( + $user->email, + 'Congratulations', + $emailerData, + $user + ); + } return $this->metaSuccess(); } else { - return $this->errorResponse(__($this->failed_verification_response), Response::HTTP_BAD_REQUEST); + return $this->errorResponse( + __($this->failed_verification_response), + Response::HTTP_BAD_REQUEST + ); } } - return $this->errorResponse(__($this->failed_verification_response), Response::HTTP_BAD_REQUEST); + return $this->errorResponse( + __($this->failed_verification_response), + Response::HTTP_BAD_REQUEST + ); } catch (\Exception $ex) { - return $this->errorResponse(__($this->failed_verification_response), Response::HTTP_BAD_REQUEST, $ex->getMessage()); + return $this->errorResponse( + __($this->failed_verification_response), + Response::HTTP_BAD_REQUEST, + $ex->getMessage() + ); } } public function functionSubmitKYC(SubmitKYCRequest $request) { - $user = auth()->user(); - $data = $request->validated(); + $user = auth()->user(); + $data = $request->validated(); $data['dob'] = \Carbon\Carbon::parse($request->dob)->format('Y-m-d'); $user->update(['member_status' => User::STATUS_INCOMPLETE]); + $this->profileRepo->updateOrCreate( [ 'user_id' => $user->id, ], $data ); + $user->reset_kyc = 0; $user->save(); return $this->metaSuccess(); } - public function verifyOwnerNode(Request $request) - { - $user = auth()->user(); - $this->profileRepo->updateConditions( - ['type_owner_node' => $request->type], - ['user_id' => $user->id] - ); - return $this->metaSuccess(); - } - - public function getOwnerNodes() - { - $user = auth()->user(); - $owners = OwnerNode::where('user_id', $user->id)->get(); - foreach ($owners as $owner) { - $email = $owner->email; - $userOwner = User::where('email', $email)->first(); - if ($userOwner) $owner->kyc_verified_at = $userOwner->kyc_verified_at; - else $owner->kyc_verified_at = null; - } - $data = []; - $data['kyc_verified_at'] = $user->kyc_verified_at; - $data['owner_node'] = $owners; - - return $this->successResponse($data); - } - - public function resendEmailOwnerNodes(ResendEmailRequest $request) - { - $user = auth()->user(); - $email = $request->email; - $owners = OwnerNode::where('user_id', $user->id)->where('email', $email)->first(); - if ($owners) { - $userOwner = User::where('email', $email)->first(); - if (!$userOwner) { - $url = $request->header('origin') ?? $request->root(); - $resetUrl = $url . '/register-type'; - Mail::to($email)->send(new AddNodeMail($resetUrl)); - } - } else - return $this->errorResponse('Email does not exist', Response::HTTP_BAD_REQUEST); - return $this->successResponse(null); - } - // Save Shuftipro Temp public function saveShuftiproTemp(Request $request) { $user = auth()->user(); + // Validator $validator = Validator::make($request->all(), [ 'reference_id' => 'required' ]); - if ($validator->fails()) return $this->validateResponse($validator->errors()); - $user_id = $user->id; - $reference_id = $request->reference_id; + if ($validator->fails()) { + return $this->validateResponse($validator->errors()); + } + + $user_id = $user->id; + $reference_id = $request->reference_id; ShuftiproTemp::where('user_id', $user_id)->delete(); - $record = new ShuftiproTemp; - $record->user_id = $user_id; + $record = new ShuftiproTemp; + $record->user_id = $user_id; $record->reference_id = $reference_id; $record->save(); @@ -720,15 +1212,20 @@ public function saveShuftiproTemp(Request $request) public function deleteShuftiproTemp(Request $request) { $user = auth()->user(); + // Validator $validator = Validator::make($request->all(), [ 'reference_id' => 'required' ]); - if ($validator->fails()) return $this->validateResponse($validator->errors()); - $user_id = $user->id; + if ($validator->fails()) { + return $this->validateResponse($validator->errors()); + } + + $user_id = $user->id; $reference_id = $request->reference_id; - $profile = Profile::where('user_id', $user_id)->first(); + $profile = Profile::where('user_id', $user_id)->first(); + if ($profile) { $profile->status = null; $profile->save(); @@ -740,36 +1237,6 @@ public function deleteShuftiproTemp(Request $request) return $this->metaSuccess(); } - // Update Shuftipro Temp Status - public function updateShuftiProTemp(Request $request) - { - $user = auth()->user(); - // Validator - $validator = Validator::make($request->all(), [ - 'reference_id' => 'required' - ]); - if ($validator->fails()) return $this->validateResponse($validator->errors()); - - $user_id = $user->id; - $reference_id = $request->reference_id; - $profile = Profile::where('user_id', $user_id)->first(); - if ($profile) { - $profile->status = 'pending'; - $profile->save(); - } - $record = ShuftiproTemp::where('user_id', $user_id) - ->where('reference_id', $reference_id) - ->first(); - if ($record) { - $record->status = 'booked'; - $record->save(); - $emailerData = EmailerHelper::getEmailerData(); - EmailerHelper::triggerAdminEmail('KYC or AML need review', $emailerData, $user); - return $this->metaSuccess(); - } - return $this->errorResponse('Fail submit AML', Response::HTTP_BAD_REQUEST); - } - // get vote list public function getVotes(Request $request) { @@ -779,40 +1246,39 @@ public function getVotes(Request $request) $status = $request->status ?? 'active'; $limit = $request->limit ?? 50; - $sort_key = $request->sort_key ?? ''; - $sort_direction = $request->sort_direction ?? ''; - if (!$sort_key) $sort_key = 'ballot.id'; - if (!$sort_direction) $sort_direction = 'desc'; + $sort_key = $request->sort_key ?? 'ballot.id'; + $sort_direction = $request->sort_direction ?? 'desc'; + + if ( + $status != 'active' && + $status != 'finish' && + $status != 'scheduled' + ) { + return $this->errorResponse( + 'Paramater invalid (status is active or finish)', + Response::HTTP_BAD_REQUEST + ); + } - if ($status != 'active' && $status != 'finish' && $status != 'scheduled') - return $this->errorResponse('Paramater invalid (status is active or finish)', Response::HTTP_BAD_REQUEST); + $now = Carbon::now('UTC'); - $now = Carbon::now('EST'); $startDate = $now->format('Y-m-d'); $startTime = $now->format('H:i:s'); if ($status == 'active') { $query = Ballot::where('status', 'active') - ->where(function ($query) use ($startDate, $startTime) { - $query->where('start_date', '<', $startDate) - ->orWhere(function ($query) use ($startDate, $startTime) { - $query->where('start_date', $startDate) - ->where('start_time', '<=', $startTime); - }); - }); + ->where('time_begin', '<=', $now); } else if ($status == 'scheduled') { $query = Ballot::where('status', 'active') - ->where(function ($query) use ($startDate, $startTime) { - $query->where('start_date', '>', $startDate) - ->orWhere(function ($query) use ($startDate, $startTime) { - $query->where('start_date', $startDate) - ->where('start_time', '>', $startTime); - }); - }); + ->where('time_begin', '>', $now); + } else { + $query = Ballot::where('status', '<>', 'active'); } - else $query = Ballot::where('status', '<>', 'active'); - $data = $query->with('vote')->orderBy($sort_key, $sort_direction)->paginate($limit); + $data = $query->with('vote')->orderBy( + $sort_key, + $sort_direction + )->paginate($limit); return $this->successResponse($data); } @@ -831,10 +1297,173 @@ public function getVoteDetail($id) $ballotFileView = BallotFileView::where('ballot_file_id', $file->id)->where('user_id', $user->id)->first(); $file->is_viewed = $ballotFileView ? 1 : 0; } - $ballot->user_vote = VoteResult::where('user_id', $user->id)->where('ballot_id', $ballot->id)->first(); + + foreach ($ballot->files as $file) { + $ballotFileView = BallotFileView::where('ballot_file_id', $file->id) + ->where('user_id', $user->id) + ->first(); + + $file->is_viewed = $ballotFileView ? 1 : 0; + } + + $ballot->user_vote = VoteResult::where('user_id', $user->id) + ->where('ballot_id', $ballot->id) + ->first(); + return $this->successResponse($ballot); } + public function requestReactivation(Request $request) + { + $user = auth()->user()->load(['addresses', 'profile']); + $addresses = $user->addresses ?? []; + + $reactivation_reason = $request->reactivationReason ?? ''; + + if ( + $addresses && + count($addresses) > 0 && + $user->node_verified_at && + $user->letter_verified_at && + $user->signature_request_id && + isset($user->profile) && + $user->profile && + $user->profile->status == 'approved' && + $user->profile->extra_status == 'Suspended' && + !$user->profile->reactivation_requested + ) { + $user->profile->reactivation_reason = $reactivation_reason; + $user->profile->reactivation_requested = true; + $user->profile->reactivation_requested_at = Carbon::now('UTC'); + $user->profile->save(); + } + + return $this->metaSuccess(); + } + + public function canRequestReactivation() + { + $user = auth()->user()->load(['addresses', 'profile']); + $user_id = $user->id; + $addresses = $user->addresses ?? []; + + $settings = Helper::getSettings(); + + $current_era_id = (int) ($settings['current_era_id'] ?? 0); + $redmarks_revoke = (int) ($settings['redmarks_revoke'] ?? 0); + $uptime_probation = (float) ($settings['uptime_probation'] ?? 0); + + $return = [ + 'canRequest' => false, + 'avg_uptime' => 0, + 'avg_redmarks' => 0 + ]; + + if ( + $addresses && + count($addresses) > 0 && + $user->node_verified_at && + $user->letter_verified_at && + $user->signature_request_id && + isset($user->profile) && + $user->profile && + $user->profile->status == 'approved' && + $user->profile->extra_status == 'Suspended' + ) { + $flag = true; + $count = 0; + foreach ($addresses as $address) { + $public_address_node = strtolower($address->public_address_node); + + if ($address->extra_status == 'Suspended') { + $count++; + + $temp = AllNodeData2::select(['id', 'uptime']) + ->where('public_key', $public_address_node) + ->where('era_id', $current_era_id) + ->where('bid_inactive', 0) + ->where('in_auction', 1) + ->where('in_current_era', 1) + ->first(); + if ($temp) { + // Check Redmarks + if ($redmarks_revoke > 0) { + $bad_marks = Helper::calculateBadMarksRevoke($temp, $public_address_node, $settings); + if ($bad_marks > $redmarks_revoke) { + $flag = false; + } + $return['avg_redmarks'] += $bad_marks; + } + + // Check Historical Performance + if ($uptime_probation > 0) { + $uptime = Helper::calculateUptime($temp, $public_address_node, $settings); + if ($uptime < $uptime_probation) { + $flag = false; + } + $return['avg_uptime'] += $uptime; + } + } + } + } + + $return['canRequest'] = $flag; + if ($count <= 0) $count = 1; + + $return['avg_redmarks'] = (int) ($return['avg_redmarks'] / $count); + $return['avg_uptime'] = (float) ($return['avg_uptime'] / $count); + $return['avg_uptime'] = round($return['avg_uptime'], 2); + } + + return $this->successResponse($return); + } + + public function canVote() + { + $user = auth()->user(); + $user_id = $user->id; + + $return = [ + 'setting_voting_eras' => 0, + 'setting_good_standing_eras' => 0, + 'good_standing_eras' => 0, + 'total_active_eras' => 0, + 'can_vote' => false + ]; + + $settings = Helper::getSettings(); + + $voting_eras_to_vote = isset($settings['voting_eras_to_vote']) ? (int) $settings['voting_eras_to_vote'] : 1; + $voting_eras_since_redmark = isset($settings['voting_eras_since_redmark']) ? (int) $settings['voting_eras_since_redmark'] : 1; + + $return['setting_voting_eras'] = $voting_eras_to_vote; + $return['setting_good_standing_eras'] = $voting_eras_since_redmark; + + $user_addresses = DB::select(" + SELECT public_address_node + FROM user_addresses + WHERE user_id = $user_id + "); + $user_addresses = $user_addresses ?? []; + + foreach ($user_addresses as $a) { + $p = $a->public_address_node ?? ''; + + $return['good_standing_eras'] = Helper::calculateVariables('good_standing_eras', $p, $settings); + $return['total_active_eras'] = Helper::calculateVariables('total_active_eras', $p, $settings); + + if ( + $return['total_active_eras'] >= $voting_eras_to_vote && + $return['good_standing_eras'] >= $voting_eras_since_redmark + ) { + $return['can_vote'] = true; + break; + } + } + + return $this->successResponse($return); + } + // vote the ballot public function vote($id, Request $request) { @@ -843,40 +1472,98 @@ public function vote($id, Request $request) return $this->errorResponse('Your access is blocked', Response::HTTP_BAD_REQUEST); $vote = $request->vote; - if (!$vote || ($vote != 'for' && $vote != 'against')) - return $this->errorResponse('Paramater invalid (vote is for or against)', Response::HTTP_BAD_REQUEST); + + if (!$vote || ($vote != 'for' && $vote != 'against')) { + return $this->errorResponse( + 'Paramater invalid (vote is for or against)', + Response::HTTP_BAD_REQUEST + ); + } + + // New check for stable member validator + $stable = false; + $addresses = UserAddress::where('user_id', $user->id)->get(); + + if (!$addresses) { + $addresses = []; + } + + $settings = Helper::getSettings(); + $current_era_id = (int) ($settings['current_era_id'] ?? 0); + + $voting_eras_to_vote = isset($settings['voting_eras_to_vote']) ? (int) $settings['voting_eras_to_vote'] : 1; + $voting_eras_since_redmark = isset($settings['voting_eras_since_redmark']) ? (int) $settings['voting_eras_since_redmark'] : 1; + + foreach ($addresses as $address) { + $p = $address->public_address_node ?? ''; + + $good_standing_eras = Helper::calculateVariables('good_standing_eras', $p, $settings); + $total_active_eras = Helper::calculateVariables('total_active_eras', $p, $settings); + + if ( + $total_active_eras >= $voting_eras_to_vote && + $good_standing_eras >= $voting_eras_since_redmark + ) { + $stable = true; + break; + } + } + + if (!$stable) { + return $this->errorResponse( + 'Validator is not stable enough to vote', + Response::HTTP_BAD_REQUEST + ); + } + $ballot = Ballot::where('id', $id)->first(); - if (!$ballot) return $this->errorResponse('Not found ballot', Response::HTTP_BAD_REQUEST); - $voteResult = VoteResult::where('user_id', $user->id)->where('ballot_id', $ballot->id)->first(); + + if (!$ballot) { + return $this->errorResponse( + 'Not found ballot', + Response::HTTP_BAD_REQUEST + ); + } + + $voteResult = VoteResult::where('user_id', $user->id) + ->where('ballot_id', $ballot->id) + ->first(); + if ($voteResult) { - if ($vote == $voteResult->type) return $this->metaSuccess(); - else { - $voteResult->type = $vote; - $voteResult->updated_at = now(); + if ($vote == $voteResult->type) { + return $this->metaSuccess(); + } else { + $voteResult->type = $vote; + $voteResult->updated_at = Carbon::now('UTC'); + if ($vote == 'for') { - $ballot->vote->for_value = $ballot->vote->for_value + 1; + $ballot->vote->for_value = $ballot->vote->for_value + 1; $ballot->vote->against_value = $ballot->vote->against_value - 1; } else { - $ballot->vote->for_value = $ballot->vote->for_value - 1; + $ballot->vote->for_value = $ballot->vote->for_value - 1; $ballot->vote->against_value = $ballot->vote->against_value + 1; } - $ballot->vote->updated_at = now(); + + $ballot->vote->updated_at = Carbon::now('UTC'); $ballot->vote->save(); $voteResult->save(); } } else { $voteResult = new VoteResult(); - $voteResult->user_id = $user->id; + $voteResult->user_id = $user->id; $voteResult->ballot_id = $ballot->id; - $voteResult->vote_id = $ballot->vote->id; - $voteResult->type = $vote; + $voteResult->vote_id = $ballot->vote->id; + $voteResult->type = $vote; $voteResult->save(); - if ($vote == 'for') - $ballot->vote->for_value = $ballot->vote->for_value + 1; - else + + if ($vote == 'for') { + $ballot->vote->for_value = $ballot->vote->for_value + 1; + } else { $ballot->vote->against_value = $ballot->vote->against_value + 1; + } + $ballot->vote->result_count = $ballot->vote->result_count + 1; - $ballot->vote->updated_at = now(); + $ballot->vote->updated_at = Carbon::now('UTC'); $ballot->vote->save(); } return $this->metaSuccess(); @@ -884,57 +1571,67 @@ public function vote($id, Request $request) public function submitViewFileBallot(Request $request, $fileId) { - $user = auth()->user(); + $user = auth()->user(); $ballotFile = BallotFile::where('id', $fileId)->first(); - if (!$ballotFile) - return $this->errorResponse('Not found ballot file', Response::HTTP_BAD_REQUEST); - $ballotFileView = BallotFileView::where('ballot_file_id', $ballotFile->id)->where('user_id', $user->id)->first(); - if ($ballotFileView) return $this->metaSuccess(); - $ballotFileView = new BallotFileView(); - $ballotFileView->ballot_file_id = $ballotFile->id; - $ballotFileView->ballot_id = $ballotFile->ballot_id; - $ballotFileView->user_id = $user->id; + + if (!$ballotFile) { + return $this->errorResponse( + 'Not found ballot file', + Response::HTTP_BAD_REQUEST + ); + } + + $ballotFileView = BallotFileView::where('ballot_file_id', $ballotFile->id) + ->where('user_id', $user->id) + ->first(); + + if ($ballotFileView) { + return $this->metaSuccess(); + } + + $ballotFileView = new BallotFileView(); + $ballotFileView->ballot_file_id = $ballotFile->id; + $ballotFileView->ballot_id = $ballotFile->ballot_id; + $ballotFileView->user_id = $user->id; $ballotFileView->save(); return $this->metaSuccess(); } - /** - * verify file casper singer - */ + public function uploadAvatar(Request $request) { try { // Validator $validator = Validator::make($request->all(), [ - 'avatar' => 'sometimes|mimes:jpeg,jpg,png,gif,webp|max:100000', + 'avatar' => 'sometimes|mimes:jpeg,jpg,png,gif,webp|max:2048', ]); if ($validator->fails()) { return $this->validateResponse($validator->errors()); } - $user = auth()->user(); + $user = auth()->user(); $filenameWithExt = $request->file('avatar')->getClientOriginalName(); - $filename = pathinfo($filenameWithExt, PATHINFO_FILENAME); - $extension = $request->file('avatar')->getClientOriginalExtension(); + $filename = pathinfo($filenameWithExt, PATHINFO_FILENAME); + $extension = $request->file('avatar')->getClientOriginalExtension(); // new filename hash - $filenamehash = md5(Str::random(10) . '_' . (string)time()); + $filenamehash = md5(Str::random(10) . '_' . (string)time()); // Filename to store $fileNameToStore = $filenamehash . '.' . $extension; // S3 file upload $S3 = new S3Client([ - 'version' => 'latest', - 'region' => getenv('AWS_DEFAULT_REGION'), + 'version' => 'latest', + 'region' => getenv('AWS_DEFAULT_REGION'), 'credentials' => [ - 'key' => getenv('AWS_ACCESS_KEY_ID'), - 'secret' => getenv('AWS_SECRET_ACCESS_KEY'), + 'key' => getenv('AWS_ACCESS_KEY_ID'), + 'secret' => getenv('AWS_SECRET_ACCESS_KEY'), ], ]); $s3result = $S3->putObject([ - 'Bucket' => getenv('AWS_BUCKET'), - 'Key' => 'client_uploads/' . $fileNameToStore, - 'SourceFile' => $request->file('avatar'), + 'Bucket' => getenv('AWS_BUCKET'), + 'Key' => 'client_uploads/' . $fileNameToStore, + 'SourceFile' => $request->file('avatar'), ]); // $ObjectURL = 'https://'.getenv('AWS_BUCKET').'.s3.amazonaws.com/client_uploads/'.$fileNameToStore; @@ -942,106 +1639,173 @@ public function uploadAvatar(Request $request) $user->save(); return $this->metaSuccess(); } catch (\Exception $ex) { - return $this->errorResponse(__('Failed upload avatar'), Response::HTTP_BAD_REQUEST, $ex->getMessage()); + return $this->errorResponse( + __('Failed upload avatar'), + Response::HTTP_BAD_REQUEST, + $ex->getMessage() + ); } } public function getMembers(Request $request) { + $settings = Helper::getSettings(); + $current_era_id = (int) ($settings['current_era_id'] ?? 0); + $search = $request->search; - $limit = $request->limit ?? 50; - - $slide_value_uptime = $request->uptime ?? 0; - $slide_value_update_responsiveness = $request->update_responsiveness ?? 0; - $slide_value_delegotors = $request->delegators ?? 0; - $slide_value_stake_amount = $request->stake_amount ?? 0; - $slide_delegation_rate = $request->delegation_rate ?? 0; - - $max_uptime = Node::max('uptime'); - $max_uptime = $max_uptime * 100; - - $max_delegators = NodeInfo::max('delegators_count'); - if(!$max_delegators || $max_delegators < 1) $max_delegators = 1; - - $max_stake_amount = NodeInfo::max('total_staked_amount'); - if(!$max_stake_amount || $max_stake_amount < 1) $max_stake_amount = 1; $sort_key = $request->sort_key ?? 'created_at'; - - $users = User::with(['metric', 'nodeInfo', 'profile']) - ->whereHas('nodeInfo') - ->where('role', 'member') - ->where(function ($query) use ($search) { - if ($search) { - $query->where('users.first_name', 'like', '%' . $search . '%') - ->orWhere('users.last_name', 'like', '%' . $search . '%'); - } - }) - ->get(); - - foreach ($users as $user) { - $latest = Node::where('node_address', strtolower($user->public_address_node)) - ->whereNotnull('protocol_version') - ->orderBy('created_at', 'desc') - ->first(); - if (!$latest) $latest = new Node(); - - $user->status = isset($user->profile) && isset($user->profile->status) ? $user->profile->status : ''; - - $uptime_nodeInfo = $user->nodeInfo->uptime; - $uptime_node = isset($latest->uptime) && $latest->uptime ? $latest->uptime * 100 : null; - $uptime_metric = isset($user->metric) && isset($user->metric->uptime) ? $user->metric->uptime : null; - - $res_nodeInfo = $user->nodeInfo->update_responsiveness ?? null; - $res_node = $latest->update_responsiveness ?? null; - $res_metric = $user->metric->update_responsiveness ?? null; - - $uptime = $uptime_nodeInfo ? $uptime_nodeInfo : ($uptime_node ? $uptime_node : ($uptime_metric ? $uptime_metric : 1)); - $res = $res_nodeInfo ? $res_nodeInfo : ($res_node ? $res_node : ($res_metric ? $res_metric : 0)); - - $delegation_rate = isset($user->nodeInfo->delegation_rate) && $user->nodeInfo->delegation_rate ? $user->nodeInfo->delegation_rate / 100 : 1; - if ($delegation_rate > 1) $delegation_rate = 1; - $delegators_count = isset($user->nodeInfo->delegators_count) && $user->nodeInfo->delegators_count ? $user->nodeInfo->delegators_count : 0; - $total_staked_amount = isset($user->nodeInfo->total_staked_amount) && $user->nodeInfo->total_staked_amount ? $user->nodeInfo->total_staked_amount : 0; - - $uptime_score = (float) (($slide_value_uptime * $uptime) / 100); - $delegation_rate_score = (float) (($slide_delegation_rate * (1 - $delegation_rate)) / 100); - $delegators_count_score = (float) ($delegators_count / $max_delegators) * $slide_value_delegotors; - $total_staked_amount_score = (float) ($total_staked_amount / $max_stake_amount) * $slide_value_stake_amount; - $res_score = (float) (($slide_value_update_responsiveness * $res) / 100); - - $user->uptime = $uptime; - $user->delegation_rate = $delegation_rate; - $user->delegators_count = $delegators_count; - $user->total_staked_amount = $total_staked_amount; - $user->totalScore = $uptime_score + $delegation_rate_score + $delegators_count_score + $total_staked_amount_score + $res_score; + + $members = DB::table('users') + ->select( + 'users.id', + 'users.pseudonym', + 'users.created_at', + 'users.approve_at', + 'users.kyc_verified_at', + 'user_addresses.node_verified_at', + 'all_node_data2.public_key', + 'all_node_data2.uptime as uptimeBase', + 'all_node_data2.bid_delegators_count', + 'all_node_data2.bid_delegation_rate', + 'all_node_data2.bid_total_staked_amount' + ) + ->join( + 'user_addresses', + 'user_addresses.user_id', + '=', + 'users.id' + ) + ->join( + 'all_node_data2', + 'all_node_data2.public_key', + '=', + 'user_addresses.public_address_node' + ) + ->where([ + 'users.banned' => 0, + 'all_node_data2.era_id' => $current_era_id + ]) + ->where(function ($query) use ($search) { + if ($search) { + $query->where('users.first_name', 'like', '%' . $search . '%') + ->orWhere('users.last_name', 'like', '%' . $search . '%') + ->orWhere('users.pseudonym', 'like', '%' . $search . '%'); + } + }) + ->get(); + + $max_delegators = 0; + $max_stake_amount = 0; + + foreach ($members as $member) { + if ((int)$member->bid_delegators_count > $max_delegators) { + $max_delegators = (int)$member->bid_delegators_count; + } + + if ((int)$member->bid_total_staked_amount > $max_stake_amount) { + $max_stake_amount = (int)$member->bid_total_staked_amount; + } } - $users = $users->sortByDesc($sort_key)->values(); - $users = Helper::paginate($users, $limit, $request->page); - return $this->successResponse($users); + foreach ($members as &$member) { + $baseObject = $member; + $baseObject->uptime = $member->uptimeBase; + $member->uptime = Helper::calculateUptime($member, $member->public_key, $settings); + + $r = $member; + $r->uptime_rate = (float) ($request->uptime ?? 0); + $r->fee_rate = (float) ($request->delegation_rate ?? 0); + $r->count_rate = (float) ($request->delegators ?? 0); + $r->stake_rate = (float) ($request->stake_amount ?? 0); + + $member->totalScore = Helper::getTotalScore($r, $max_delegators, $max_stake_amount); + } + + $members = $members->sortByDesc($sort_key)->values(); + + return $this->successResponse($members); } - public function getMemberDetail($id, Request $request) - { - $public_address_node = $request->get('public_address_node') ?? null; + public function getMemberDetail($id, Request $request) { $user = User::where('id', $id)->first(); + if (!$user || $user->role == 'admin') { + return $this->errorResponse( + __('api.error.not_found'), + Response::HTTP_NOT_FOUND + ); + } Helper::getAccountInfoStandard($user); - if (!$user || $user->role == 'admin') - return $this->errorResponse(__('api.error.not_found'), Response::HTTP_NOT_FOUND); - $user->metric = Helper::getNodeInfo($user, $public_address_node); - $response = $user->load(['profile', 'addresses']); + $current_era_id = Helper::getCurrentERAId(); + + $response = [ + 'id' => $user->id, + 'full_name' => $user->full_name, + 'avatar_url' => $user->avatar_url, + 'first_name' => $user->first_name, + 'last_name' => $user->last_name, + 'email' => $user->email, + 'pseudonym' => $user->pseudonym, + 'telegram' => $user->telegram, + 'type' => $user->type, + 'entity_name' => $user->entity_name, + 'entity_type' => $user->entity_type, + 'entity_register_number' => $user->entity_register_number, + 'entity_register_country' => $user->entity_register_country, + // 'entity_tax' => $user->entity_tax, + 'public_address_node' => $user->public_address_node, + 'node_verified_at' => $user->node_verified_at, + 'member_status' => $user->member_status, + 'message_content' => $user->message_content, + 'email_verified_at' => $user->email_verified_at, + 'kyc_verified_at' => $user->kyc_verified_at, + 'letter_verified_at' => $user->letter_verified_at, + 'letter_rejected_at' => $user->letter_rejected_at, + 'approve_at' => $user->approve_at, + 'role' => $user->role, + 'node_status' => $user->node_status + ]; - unset($response->last_login_at); - unset($response->last_login_ip_address); + if ($user->profile) { + $response['profile'] = [ + 'id' => $user->profile->id, + 'status' => $user->profile->status, + 'extra_status' => $user->profile->extra_status, + 'casper_association_kyc_hash' => $user->profile->casper_association_kyc_hash, + 'blockchain_name' => $user->profile->blockchain_name, + 'blockchain_desc' => $user->profile->blockchain_desc, + 'type' => $user->profile->type + ]; + } else { + $response['profile'] = [ + 'type' => $user->type + ]; + } - if (isset($response->profile)) { - unset($response->profile->dob); - unset($response->profile->address); - unset($response->profile->city); - unset($response->profile->zip); + $response['addresses'] = $user->addresses ?? []; + + foreach ($response['addresses'] as &$addressItem) { + $temp = AllNodeData2::select([ + 'uptime', + 'bid_delegators_count', + 'bid_delegation_rate', + 'bid_self_staked_amount', + 'bid_total_staked_amount' + ]) + ->where('public_key', $addressItem->public_address_node) + ->where('era_id', $current_era_id) + ->orderBy('id', 'desc') + ->first() + ->toArray(); + if ($temp) { + foreach ($temp as $key => $value) { + if ($key == 'uptime') $value = round((float) $value, 2); + $addressItem->$key = $value; + } + $addressItem->update_responsiveness = 100; + } } return $this->successResponse($response); @@ -1049,21 +1813,27 @@ public function getMemberDetail($id, Request $request) public function getCaKycHash($hash) { - if (!ctype_xdigit($hash)) - return $this->errorResponse(__('api.error.not_found'), Response::HTTP_NOT_FOUND); + if (!ctype_xdigit($hash)) { + return $this->errorResponse( + __('api.error.not_found'), + Response::HTTP_NOT_FOUND + ); + } $selection = DB::select(" - SELECT a.casper_association_kyc_hash as proof_hash, b.reference_id, b.status, c.pseudonym - FROM profile as a + SELECT + a.casper_association_kyc_hash AS proof_hash, + b.reference_id, b.status, + c.pseudonym + FROM profile AS a LEFT JOIN shuftipro AS b ON a.user_id = b.user_id LEFT JOIN users AS c ON b.user_id = c.id WHERE a.casper_association_kyc_hash = '$hash' "); - $selection = $selection[0] ?? array(); - - return $this->successResponse($selection); + + return $this->successResponse($selection[0] ?? []); } public function getMyVotes(Request $request) @@ -1073,8 +1843,8 @@ public function getMyVotes(Request $request) return $this->successResponse(['data' => []]); $limit = $request->limit ?? 50; - $user = auth()->user(); - $data = VoteResult::where('vote_result.user_id', $user->id) + $user = auth()->user(); + $data = VoteResult::where('vote_result.user_id', $user->id) ->join('ballot', function ($query) use ($user) { $query->on('vote_result.ballot_id', '=', 'ballot.id'); }) @@ -1093,79 +1863,141 @@ public function getMyVotes(Request $request) public function checkCurrentPassword(Request $request) { $user = auth()->user(); - if (Hash::check($request->current_password, $user->password)) + + if (Hash::check($request->current_password, $user->password)) { return $this->metaSuccess(); - else - return $this->errorResponse(__('Invalid password'), Response::HTTP_BAD_REQUEST); + } else { + return $this->errorResponse( + __('Invalid password'), + Response::HTTP_BAD_REQUEST + ); + } } public function settingUser(Request $request) { $user = auth()->user(); - if ($request->new_password) $user->password = bcrypt($request->new_password); + + if ($request->new_password) { + $user->password = bcrypt($request->new_password); + } if ($request->username) { $checkUsername = User::where('username', $request->username) - ->where('username', '!=', $user->username) - ->first(); - if ($checkUsername) - return $this->errorResponse(__('this username has already been taken'), Response::HTTP_BAD_REQUEST); + ->where('username', '!=', $user->username) + ->first(); + + if ($checkUsername) { + return $this->errorResponse( + __('this username has already been taken'), + Response::HTTP_BAD_REQUEST + ); + } + $user->username = $request->username; } - if (isset($request->twoFA_login)) $user->twoFA_login = $request->twoFA_login; + if (isset($request->twoFA_login)) { + $user->twoFA_login = $request->twoFA_login; + } if ($request->email && $request->email != $user->email) { $emailParam = $request->email; - $checkEmail = User::where(function ($query) use ($emailParam) { - $query->where('email', $emailParam) - ->orWhere('new_email', $emailParam); - }) - ->where('id', '!=', $user->id) - ->first(); + $checkEmail = User::where( + function ($query) use ($emailParam) { + $query->where('email', $emailParam) + ->orWhere('new_email', $emailParam); + } + ) + ->where('id', '!=', $user->id) + ->first(); $currentEmail = $user->email; - $newEmail = $request->email; - if ($checkEmail) - return $this->errorResponse(__('this email has already been taken'), Response::HTTP_BAD_REQUEST); + $newEmail = $request->email; + + if ($checkEmail) { + return $this->errorResponse( + __('this email has already been taken'), + Response::HTTP_BAD_REQUEST + ); + } + $user->new_email = $newEmail; // Current Email $codeCurrentEmail = Str::random(6); - $url = $request->header('origin') ?? $request->root(); - $urlCurrentEmail = $url . '/change-email/cancel-changes?code=' . $codeCurrentEmail . '&email=' . urlencode($currentEmail); + $url = $request->header('origin') ?? $request->root(); + $urlCurrentEmail = ( + $url . + '/change-email/cancel-changes?code=' . + $codeCurrentEmail . + '&email=' . + urlencode($currentEmail) + ); + $newMemberData = [ - 'title' => 'Are you trying to update your email?', + 'title' => 'Are you trying to update your email?', 'content' => 'You recently requested to update your email address with the Casper Association Portal. If this is correct, click the link sent to your new email address to activate it.
If you did not initiate this update, your account could be compromised. Click the button to cancel the change', - 'url' => $urlCurrentEmail, - 'action' => 'cancel' + 'url' => $urlCurrentEmail, + 'action' => 'cancel' ]; - Mail::to($currentEmail)->send(new UserConfirmEmail($newMemberData['title'], $newMemberData['content'], $newMemberData['url'], $newMemberData['action'])); - VerifyUser::where('email', $currentEmail)->where('type', VerifyUser::TYPE_CANCEL_EMAIL)->delete(); - $verify = new VerifyUser(); - $verify->code = $codeCurrentEmail; - $verify->email = $currentEmail; - $verify->type = VerifyUser::TYPE_CANCEL_EMAIL; - $verify->created_at = now(); + + Mail::to($currentEmail)->send( + new UserConfirmEmail( + $newMemberData['title'], + $newMemberData['content'], + $newMemberData['url'], + $newMemberData['action'] + ) + ); + + VerifyUser::where('email', $currentEmail) + ->where('type', VerifyUser::TYPE_CANCEL_EMAIL) + ->delete(); + + $verify = new VerifyUser(); + $verify->code = $codeCurrentEmail; + $verify->email = $currentEmail; + $verify->type = VerifyUser::TYPE_CANCEL_EMAIL; + $verify->created_at = Carbon::now('UTC'); $verify->save(); // new email $codeNewEmail = Str::random(6); - $urlNewEmail = $url . '/change-email/confirm?code=' . $codeNewEmail . '&email=' . urlencode($newEmail); + $urlNewEmail = ( + $url . + '/change-email/confirm?code=' . + $codeNewEmail . + '&email=' . + urlencode($newEmail) + ); + $newMemberData = [ - 'title' => 'You recently updated your email', + 'title' => 'You recently updated your email', 'content' => 'You recently requested to update your email address with the Casper Association Portal. If this is correct, click the button below to confirm the change.
If you received this email in error, you can simply delete it', - 'url' => $urlNewEmail, - 'action' => 'confirm' + 'url' => $urlNewEmail, + 'action' => 'confirm' ]; - Mail::to($newEmail)->send(new UserConfirmEmail($newMemberData['title'], $newMemberData['content'], $newMemberData['url'], $newMemberData['action'])); - VerifyUser::where('email', $newEmail)->where('type', VerifyUser::TYPE_CONFIRM_EMAIL)->delete(); - $verify = new VerifyUser(); - $verify->email = $newEmail; - $verify->code = $codeNewEmail; - $verify->type = VerifyUser::TYPE_CONFIRM_EMAIL; - $verify->created_at = now(); + + Mail::to($newEmail)->send( + new UserConfirmEmail( + $newMemberData['title'], + $newMemberData['content'], + $newMemberData['url'], + $newMemberData['action'] + ) + ); + + VerifyUser::where('email', $newEmail) + ->where('type', VerifyUser::TYPE_CONFIRM_EMAIL) + ->delete(); + + $verify = new VerifyUser(); + $verify->email = $newEmail; + $verify->code = $codeNewEmail; + $verify->type = VerifyUser::TYPE_CONFIRM_EMAIL; + $verify->created_at = Carbon::now('UTC'); $verify->save(); } $user->save(); @@ -1175,74 +2007,112 @@ public function settingUser(Request $request) public function cancelChangeEmail(Request $request) { - $verify = VerifyUser::where('email', $request->email)->where('type', VerifyUser::TYPE_CANCEL_EMAIL) - ->where('code', $request->code)->first(); + $verify = VerifyUser::where('email', $request->email) + ->where('type', VerifyUser::TYPE_CANCEL_EMAIL) + ->where('code', $request->code) + ->first(); + if ($verify) { $user = User::where('email', $request->email)->first(); + if ($user) { $user->new_email = null; $user->save(); $verify->delete(); - VerifyUser::where('email', $user->new_email)->where('type', VerifyUser::TYPE_CONFIRM_EMAIL)->delete(); + + VerifyUser::where('email', $user->new_email) + ->where('type', VerifyUser::TYPE_CONFIRM_EMAIL) + ->delete(); + return $this->successResponse($user); } - return $this->errorResponse(__('Fail cancel change email'), Response::HTTP_BAD_REQUEST); + + return $this->errorResponse( + __('User email not found'), + Response::HTTP_BAD_REQUEST + ); } - return $this->errorResponse(__('Fail cancel change email'), Response::HTTP_BAD_REQUEST); + + return $this->errorResponse( + __('Failed to cancel email change'), + Response::HTTP_BAD_REQUEST + ); } public function confirmChangeEmail(Request $request) { $verify = VerifyUser::where('email', $request->email) - ->where('type', VerifyUser::TYPE_CONFIRM_EMAIL) - ->where('code', $request->code) - ->first(); + ->where('type', VerifyUser::TYPE_CONFIRM_EMAIL) + ->where('code', $request->code) + ->first(); + if ($verify) { $user = User::where('new_email', $request->email)->first(); + if ($user) { - VerifyUser::where('email', $user->email)->where('type', VerifyUser::TYPE_CANCEL_EMAIL)->delete(); + VerifyUser::where('email', $user->email) + ->where('type', VerifyUser::TYPE_CANCEL_EMAIL) + ->delete(); + $user->new_email = null; - $user->email = $request->email; + $user->email = $request->email; $user->save(); $verify->delete(); return $this->successResponse($user); } - return $this->errorResponse(__('Fail confirm change email'), Response::HTTP_BAD_REQUEST); + + return $this->errorResponse( + __('User email not found'), + Response::HTTP_BAD_REQUEST + ); } - return $this->errorResponse(__('Fail confirm change email'), Response::HTTP_BAD_REQUEST); + return $this->errorResponse( + __('Failed to confirm email change'), + Response::HTTP_BAD_REQUEST + ); } public function checkLogin2FA(Request $request) { - $user = auth()->user(); + $user = auth()->user(); $verify = VerifyUser::where('email', $user->email) - ->where('type', VerifyUser::TYPE_LOGIN_TWO_FA) - ->where('code', $request->code) - ->first(); + ->where('type', VerifyUser::TYPE_LOGIN_TWO_FA) + ->where('code', $request->code) + ->first(); + if ($verify) { $verify->delete(); $user->twoFA_login_active = 0; $user->save(); return $this->metaSuccess(); } - return $this->errorResponse(__('Fail check twoFA code'), Response::HTTP_BAD_REQUEST); + + return $this->errorResponse( + __('Fail check twoFA code'), + Response::HTTP_BAD_REQUEST + ); } public function resend2FA() { $user = auth()->user(); + if ($user->twoFA_login == 1) { - VerifyUser::where('email', $user->email)->where('type', VerifyUser::TYPE_LOGIN_TWO_FA)->delete(); - $code = Str::random(6); - $verify = new VerifyUser(); - $verify->email = $user->email; - $verify->type = VerifyUser::TYPE_LOGIN_TWO_FA; - $verify->code = $code; - $verify->created_at = now(); + VerifyUser::where('email', $user->email) + ->where('type', VerifyUser::TYPE_LOGIN_TWO_FA) + ->delete(); + + $code = Str::random(6); + $verify = new VerifyUser(); + $verify->email = $user->email; + $verify->type = VerifyUser::TYPE_LOGIN_TWO_FA; + $verify->code = $code; + $verify->created_at = Carbon::now('UTC'); $verify->save(); Mail::to($user)->send(new LoginTwoFA($code)); return $this->metaSuccess(); } + return $this->errorResponse(__('Please enable 2Fa setting'), Response::HTTP_BAD_REQUEST); } @@ -1250,21 +2120,36 @@ public function getLockRules() { $user = auth()->user(); - $ruleKycNotVerify = LockRules::where('type', 'kyc_not_verify')->where('is_lock', 1) - ->orderBy('id', 'ASC')->select(['id', 'screen'])->get(); - $ruleKycNotVerify1 = array_map(function ($object) { - return $object->screen; - }, $ruleKycNotVerify->all()); - $ruleStatusIsPoor = LockRules::where('type', 'status_is_poor')->where('is_lock', 1) - ->orderBy('id', 'ASC')->select(['id', 'screen'])->get(); - $ruleStatusIsPoor1 = array_map(function ($object) { - return $object->screen; - }, $ruleStatusIsPoor->all()); + $ruleKycNotVerify = LockRules::where('type', 'kyc_not_verify') + ->where('is_lock', 1) + ->orderBy('id', 'ASC') + ->select(['id', 'screen']) + ->get(); + + $ruleKycNotVerify1 = array_map( + function ($object) { + return $object->screen; + }, + $ruleKycNotVerify->all() + ); + + $ruleStatusIsPoor = LockRules::where('type', 'status_is_poor') + ->where('is_lock', 1) + ->orderBy('id', 'ASC') + ->select(['id', 'screen']) + ->get(); + + $ruleStatusIsPoor1 = array_map( + function ($object) { + return $object->screen; + }, + $ruleStatusIsPoor->all() + ); $data = [ 'kyc_not_verify' => $ruleKycNotVerify1, 'status_is_poor' => $ruleStatusIsPoor1, - 'node_status' => $user->node_status + 'node_status' => $user->node_status ]; return $this->successResponse($data); } @@ -1272,90 +2157,67 @@ public function getLockRules() public function getListNodesBy(Request $request) { $user = auth()->user(); - $addresses = UserAddress::where('user_id', $user->id)->orderBy('id', 'asc')->get(); + $addresses = $user->addresses ?? []; + + $current_era_id = Helper::getCurrentERAId(); + + foreach ($addresses as &$addressItem) { + $temp = AllNodeData2::select([ + 'uptime', + 'bid_delegators_count', + 'bid_delegation_rate', + 'bid_self_staked_amount', + 'bid_total_staked_amount' + ]) + ->where('public_key', $addressItem->public_address_node) + ->where('era_id', $current_era_id) + ->orderBy('id', 'desc') + ->first() + ->toArray(); + if ($temp) { + foreach ($temp as $key => $value) { + if ($key == 'uptime') $value = round((float) $value, 2); + $addressItem->$key = $value; + } + $addressItem->update_responsiveness = 100; + } + } + return $this->successResponse([ 'addresses' => $addresses, ]); } - public function getListNodes(Request $request) - { - $limit = $request->limit ?? 50; - - $nodes = UserAddress::select([ - 'users.id as user_id', - 'users.pseudonym', - 'user_addresses.public_address_node', - 'user_addresses.is_fail_node', - 'user_addresses.rank', - 'profile.blockchain_name', - 'profile.blockchain_desc', - ]) - ->leftJoin('users', 'users.id', '=', 'user_addresses.user_id') - ->leftJoin('profile', 'profile.user_id', '=', 'users.id') - ->where('users.banned', 0) - ->whereNotNull('users.public_address_node') - ->orderBy('user_addresses.rank', 'asc') - ->paginate($limit); - - return $this->successResponse($nodes); - } - public function infoDashboard() { $user = auth()->user(); $delegators = 0; $stake_amount = 0; - $nodeInfo = NodeInfo::where('node_address', strtolower($user->public_address_node))->first(); + $lower_address = strtolower($user->public_address_node); + + $nodeInfo = DB::select(" + SELECT * + FROM all_node_data2 + WHERE public_key = '$lower_address' + ORDER BY era_id DESC + LIMIT 1 + "); + $nodeInfo = $nodeInfo[0] ?? null; + if ($nodeInfo) { - $delegators = $nodeInfo->delegators_count; - $stake_amount = $nodeInfo->total_staked_amount; + $delegators = $nodeInfo->bid_delegators_count; + $stake_amount = $nodeInfo->bid_total_staked_amount; } + $totalPin = DiscussionPin::where('user_id', $user->id)->count(); + $response['totalNewDiscusstion'] = $user->new_threads; $response['totalPinDiscusstion'] = $totalPin; $response['rank'] = $user->rank; $response['delegators'] = $delegators; $response['stake_amount'] = $stake_amount; - return $this->successResponse($response); - } - - public function getEarningByNode($node) - { - $node = strtolower($node); - $user = User::where('public_address_node', $node)->first(); - $nodeInfo = NodeInfo::where('node_address', $node)->first(); - $mbs = NodeInfo::max('mbs'); - if ($user && $nodeInfo) { - return $this->successResponse([ - 'daily_earning' => $nodeInfo->daily_earning, - 'total_earning' => $nodeInfo->total_earning, - 'mbs' => $mbs, - ]); - } else { - return $this->successResponse([ - 'mbs' => $mbs, - ]); - } - } - public function getChartEarningByNode($node) - { - $node = strtolower($node); - $user = User::where('public_address_node', $node)->first(); - if ($user) { - $nodeHelper = new NodeHelper(); - $result_day = $nodeHelper->getValidatorRewards($node, 'day'); - $result_week = $nodeHelper->getValidatorRewards($node, 'week'); - $result_month = $nodeHelper->getValidatorRewards($node, 'month'); - $result_year = $nodeHelper->getValidatorRewards($node, 'year'); - return $this->successResponse([ - 'day' => $result_day, - 'week' => $result_week, - 'month' => $result_month, - 'year' => $result_year, - ]); - } else return $this->successResponse(null); + return $this->successResponse($response); } public function getMembershipFile() @@ -1371,12 +2233,4 @@ public function membershipAgreement() $user->save(); return $this->metaSuccess(); } - - public function checkResetKyc() - { - $user = auth()->user(); - $user->reset_kyc = 0; - $user->save(); - return $this->metaSuccess(); - } } \ No newline at end of file diff --git a/app/Http/Controllers/Api/V1/VerificationController.php b/app/Http/Controllers/Api/V1/VerificationController.php index 08c2d92d..06a1abd9 100644 --- a/app/Http/Controllers/Api/V1/VerificationController.php +++ b/app/Http/Controllers/Api/V1/VerificationController.php @@ -42,8 +42,7 @@ public function submitNode(Request $request) { 'entity_name' => 'required', 'entity_type' => 'required', 'entity_registration_number' => 'required', - 'entity_registration_country' => 'required', - 'vat_number' => 'required' + 'entity_registration_country' => 'required' ]); if ($validator2->fails()) { return $this->validateResponse($validator2->errors()); @@ -53,7 +52,7 @@ public function submitNode(Request $request) { $profile->entity_type = $request->entity_type; $profile->entity_registration_number = $request->entity_registration_number; $profile->entity_registration_country = $request->entity_registration_country; - $profile->vat_number = $request->vat_number; + $profile->vat_number = $request->vat_number ?? null; } else { $profile->entity_name = null; $profile->entity_type = null; @@ -78,7 +77,6 @@ public function submitDetail(Request $request) { // 'page_number' => 'required|integer', 'dob' => 'required', ]); - if ($validator1->fails()) { return $this->validateResponse($validator1->errors()); } @@ -110,7 +108,8 @@ public function uploadDocument(Request $request) { // Validator $validator = Validator::make($request->all(), [ 'files' => 'array', - 'files.*' => 'file|max:100000|mimes:pdf,docx,doc,txt,rtf' + // 'files.*' => 'file|max:100000|mimes:pdf,jpeg,jpg,png,txt,rtf' + 'files.*' => 'file|max:2048|mimes:pdf,jpeg,jpg,png,txt,rtf' ]); if ($validator->fails()) { return $this->validateResponse($validator->errors()); @@ -152,22 +151,6 @@ public function uploadDocument(Request $request) { $documentFile->url = $ObjectURL; $documentFile->save(); } - - /* old - $name = $file->getClientOriginalName(); - $folder = 'document/' . $user->id; - $path = $file->storeAs($folder, $name); - $url = Storage::url($path); - $documentFile = DocumentFile::where('user_id', $user->id)->where('name', $name)->first(); - if (!$documentFile) { - $documentFile = new DocumentFile(); - $documentFile->user_id = $user->id; - $documentFile->name = $name; - $documentFile->path = $path; - $documentFile->url = $url; - $documentFile->save(); - } - */ } } $response = DocumentFile::where('user_id', $user->id)->get(); @@ -176,15 +159,4 @@ public function uploadDocument(Request $request) { return $this->errorResponse(__('Failed upload file'), Response::HTTP_BAD_REQUEST, $ex->getMessage()); } } - - public function removeDocument($id) { - $user = auth()->user(); - $documentFile = DocumentFile::where('user_id', $user->id)->where('id', $id)->first(); - if ($documentFile) { - Storage::delete($documentFile->path); - $documentFile->delete(); - } - $response = DocumentFile::where('user_id', $user->id)->get(); - return $this->successResponse($response); - } -} +} \ No newline at end of file diff --git a/app/Http/EmailerHelper.php b/app/Http/EmailerHelper.php index 69205eba..5ce8118a 100644 --- a/app/Http/EmailerHelper.php +++ b/app/Http/EmailerHelper.php @@ -16,7 +16,7 @@ public static function getEmailerData() { 'admins' => [], 'triggerAdmin' => [], 'triggerUser' => [], - 'triggerMember' => [] + 'triggerMember' => [] ]; $admins = EmailerAdmin::where('id', '>', 0)->orderBy('email', 'asc')->get(); @@ -50,40 +50,53 @@ public static function getEmailerData() { } // Send Admin Email - public static function triggerAdminEmail($title, $emailerData, $user = null) { - if (count($emailerData['admins'] ?? [])) { - $item = $emailerData['triggerAdmin'][$title] ?? null; - if ($item) { - $content = $item['content']; - $subject =$item['subject']; - if ($user) { - $name = $user->first_name . ' ' . $user->last_name; - $content = str_replace('[name]', $name, $content); - $subject = str_replace('[name]', $name, $subject); - $content = str_replace('[email]', $user->email, $content); - $subject = str_replace('[email]', $user->email, $subject); - } - Mail::to($emailerData['admins'])->send(new AdminAlert($subject, $content)); - } - } - } + public static function triggerAdminEmail($title, $emailerData, $user = null) { + if (count($emailerData['admins'] ?? [])) { + $item = $emailerData['triggerAdmin'][$title] ?? null; + if ($item) { + $content = $item['content']; + $subject =$item['subject']; + if ($user) { + $name = $user->first_name . ' ' . $user->last_name; + $content = str_replace('[name]', $name, $content); + $subject = str_replace('[name]', $name, $subject); + $content = str_replace('[email]', $user->email, $content); + $subject = str_replace('[email]', $user->email, $subject); + } + Mail::to($emailerData['admins'])->send(new AdminAlert($subject, $content)); + } + } + } - // Send User Email - public static function triggerUserEmail($to, $title, $emailerData, $user = null, $userAddress = null) { - $item = $emailerData['triggerUser'][$title] ?? null; - if ($item) { + // Send User Email + public static function triggerUserEmail($to, $title, $emailerData, $user = null, $userAddress = null, $extraOptions = []) { + $item = $emailerData['triggerUser'][$title] ?? null; + if ($item) { $content = $item['content']; $subject = $item['subject']; - if ($user) { - $name = $user->first_name . ' ' . $user->last_name; - $content = str_replace('[name]', $name, $content); - $subject = str_replace('[name]', $name, $subject); - $content = str_replace('[email]', $user->email, $content); - if ($userAddress) $content = str_replace('[node address]', $userAddress->public_address_node, $content); - else $content = str_replace('[node address]', $user->public_address_node, $content); - $subject = str_replace('[email]', $user->email, $subject); - } - Mail::to($to)->send(new UserAlert($subject, $content)); - } - } + if ($user) { + if (isset($user->first_name) && isset($user->last_name)) { + $name = $user->first_name . ' ' . $user->last_name; + $subject = str_replace('[name]', $name, $subject); + $content = str_replace('[name]', $name, $content); + } + if (isset($user->email)) { + $subject = str_replace('[email]', $user->email, $subject); + $content = str_replace('[email]', $user->email, $content); + } + if (isset($extraOptions['perk_title'])) { + $content = str_replace('[perk]', $extraOptions['perk_title'], $content); + } + if (isset($extraOptions['vote_title'])) { + $content = str_replace('[vote]', $extraOptions['vote_title'], $content); + } + if ($userAddress && isset($userAddress->public_address_node)) { + $content = str_replace('[node address]', $userAddress->public_address_node, $content); + } else if (isset($user->public_address_node)) { + $content = str_replace('[node address]', $user->public_address_node, $content); + } + } + Mail::to($to)->send(new UserAlert($subject, $content)); + } + } } \ No newline at end of file diff --git a/app/Http/Requests/Api/RegisterEntityRequest.php b/app/Http/Requests/Api/RegisterEntityRequest.php index bc55d4bd..c7be90cc 100644 --- a/app/Http/Requests/Api/RegisterEntityRequest.php +++ b/app/Http/Requests/Api/RegisterEntityRequest.php @@ -29,8 +29,10 @@ public function rules() 'entity_register_number' => 'required|string|max:255', 'entity_register_country' => 'required|string|max:255', 'entity_tax' => 'nullable|string|max:255', - 'first_name' => 'required|regex:/^[A-Za-z. ]{1,255}$/', - 'last_name' => 'required|regex:/^[A-Za-z. ]{1,255}$/', + // 'first_name' => 'required|regex:/^[A-Za-z. ]{1,255}$/', + 'first_name' => 'required', + // 'last_name' => 'required|regex:/^[A-Za-z. ]{1,255}$/', + 'last_name' => 'required', 'email' => 'required|email|max:256|unique:users', 'password' => 'required|min:8|max:80', 'pseudonym' => 'required|alpha_num|max:200|unique:users', diff --git a/app/Http/Requests/Api/RegisterIndividualRequest.php b/app/Http/Requests/Api/RegisterIndividualRequest.php index ea4fe781..ec643993 100644 --- a/app/Http/Requests/Api/RegisterIndividualRequest.php +++ b/app/Http/Requests/Api/RegisterIndividualRequest.php @@ -24,8 +24,10 @@ public function authorize() public function rules() { return [ - 'first_name' =>'required|regex:/^[A-Za-z. ]{2,255}$/', - 'last_name' =>'required|regex:/^[A-Za-z. ]{2,255}$/', + // 'first_name' =>'required|regex:/^[A-Za-z. ]{2,255}$/', + 'first_name' =>'required', + // 'last_name' =>'required|regex:/^[A-Za-z. ]{2,255}$/', + 'last_name' =>'required', 'email' => 'required|email|max:256|unique:users', 'password' => 'required|min:8|max:80', 'pseudonym' => 'required|alpha_num|max:200|unique:users', diff --git a/app/Jobs/BallotNotification.php b/app/Jobs/BallotNotification.php new file mode 100644 index 00000000..35a00e3a --- /dev/null +++ b/app/Jobs/BallotNotification.php @@ -0,0 +1,82 @@ +ballot = $ballot; + } + + public function handle() { + $settings = Helper::getSettings(); + $members = Helper::getActiveMembers(); + + $voting_eras_to_vote = isset($settings['voting_eras_to_vote']) ? (int) $settings['voting_eras_to_vote'] : 1; + $voting_eras_since_redmark = isset($settings['voting_eras_since_redmark']) ? (int) $settings['voting_eras_since_redmark'] : 1; + + if ($members && count($members) > 0) { + $emails = $processed = []; + foreach ($members as $member) { + $userId = (int) $member->id; + $email = $member->email; + + if (!in_array($email, $emails) && !in_array($userId, $processed)) { + $canVote = false; + $processed[] = $userId; + + $userAddresses = UserAddress::select('public_address_node') + ->where('user_id', $userId) + ->get(); + if ($userAddresses && count($userAddresses) > 0) { + foreach ($userAddresses as $addressRecord) { + $p = $addressRecord->public_address_node ?? ''; + + $good_standing_eras = Helper::calculateVariables('good_standing_eras', $p, $settings); + $total_active_eras = Helper::calculateVariables('total_active_eras', $p, $settings); + + if ( + $total_active_eras >= $voting_eras_to_vote && + $good_standing_eras >= $voting_eras_since_redmark + ) { + $canVote = true; + break; + } + } + } + + if ($canVote) { + $emails[] = $email; + } + } + } + if (count($emails) > 0) { + $extraOptions = [ + 'vote_title' => $this->ballot->title ?? '' + ]; + $emailerData = EmailerHelper::getEmailerData(); + foreach ($emails as $email) { + $user = new \stdClass(); + $user->email = $email; + EmailerHelper::triggerUserEmail($email, 'New Vote Started', $emailerData, $user, null, $extraOptions); + } + } + } + } +} \ No newline at end of file diff --git a/app/Jobs/BallotReminder24.php b/app/Jobs/BallotReminder24.php new file mode 100644 index 00000000..eea03cbd --- /dev/null +++ b/app/Jobs/BallotReminder24.php @@ -0,0 +1,100 @@ +ballot = $ballot; + } + + public function handle() { + if (!$this->ballot) return; + + $voteResults = $this->ballot->voteResults ?? []; + $voteUsers = []; + if ($voteResults && count($voteResults) > 0) { + foreach ($voteResults as $item) { + $voteUsers[] = (int) $item->user_id; + } + } + + $settings = Helper::getSettings(); + $members = Helper::getActiveMembers(); + + $voting_eras_to_vote = isset($settings['voting_eras_to_vote']) ? (int) $settings['voting_eras_to_vote'] : 1; + $voting_eras_since_redmark = isset($settings['voting_eras_since_redmark']) ? (int) $settings['voting_eras_since_redmark'] : 1; + + if ($members && count($members) > 0) { + $emails = $processed = []; + foreach ($members as $member) { + $userId = (int) $member->id; + $email = $member->email; + + if ( + !in_array($email, $emails) && + !in_array($userId, $processed) && + !in_array($userId, $voteUsers) + ) { + $canVote = false; + $processed[] = $userId; + + $userAddresses = UserAddress::select('public_address_node') + ->where('user_id', $userId) + ->get(); + if ($userAddresses && count($userAddresses) > 0) { + foreach ($userAddresses as $addressRecord) { + $p = $addressRecord->public_address_node ?? ''; + + $good_standing_eras = Helper::calculateVariables('good_standing_eras', $p, $settings); + $total_active_eras = Helper::calculateVariables('total_active_eras', $p, $settings); + + if ( + $total_active_eras >= $voting_eras_to_vote && + $good_standing_eras >= $voting_eras_since_redmark + ) { + $canVote = true; + break; + } + } + } + + if ($canVote) { + $emails[] = $email; + } + } + } + + if (count($emails) > 0) { + $extraOptions = [ + 'vote_title' => $this->ballot->title ?? '' + ]; + $emailerData = EmailerHelper::getEmailerData(); + foreach ($emails as $email) { + $user = new \stdClass(); + $user->email = $email; + EmailerHelper::triggerUserEmail($email, '24hr Vote Reminder', $emailerData, $user, null, $extraOptions); + } + } + } + + $this->ballot->reminder_24_sent = true; + $this->ballot->save(); + } +} \ No newline at end of file diff --git a/app/Jobs/EmailerUserJob.php b/app/Jobs/EmailerUserJob.php new file mode 100644 index 00000000..22212827 --- /dev/null +++ b/app/Jobs/EmailerUserJob.php @@ -0,0 +1,53 @@ +user = $user; + $this->title = $title; + } + + /** + * Execute the job. + * + * @return void + */ + public function handle() + { + if (!$this->user || !$this->title) { + return; + } + + $user = $this->user; + $title = $this->title; + $email = $user->email ?? ''; + + if ($email) { + $emailerData = EmailerHelper::getEmailerData(); + EmailerHelper::triggerUserEmail($email, $title, $emailerData, $user); + } + } +} \ No newline at end of file diff --git a/app/Jobs/NewUpgradeNotification.php b/app/Jobs/NewUpgradeNotification.php new file mode 100644 index 00000000..66f1758f --- /dev/null +++ b/app/Jobs/NewUpgradeNotification.php @@ -0,0 +1,102 @@ +upgrade = $upgrade; + } + + /** + * Execute the job. + * + * @return void + */ + public function handle() + { + if (!$this->upgrade) return; + + $upgrade = $this->upgrade; + $emails = []; + + // Fetch Upgrade List + $items = UpgradeList::all(); + if ($items && count($items) > 0) { + foreach ($items as $item) { + $email = $item->email; + if (!in_array($email, $emails)) { + $emails[] = $email; + } + } + } + + // Fetch Valid Users + $users = User::select('email') + ->has('addresses') + ->where('banned', 0) + ->where('role', 'member') + ->whereNotNull('public_address_node') + ->whereNotNull('signature_request_id') + ->whereNotNull('signed_file') + ->whereNotNull('node_verified_at') + ->whereNotNull('letter_file') + ->whereNotNull('letter_verified_at') + ->where(function ($query) { + $query->doesntHave('profile') + ->orWhereHas('profile', function ($query2) { + $query2->where('profile.extra_status', '!=', 'Suspended') + ->orWhereNull('profile.extra_status'); + }); + }) + ->get(); + if ($users && count($users) > 0) { + foreach ($users as $user) { + $email = $user->email; + if (!in_array($email, $emails)) { + $emails[] = $email; + } + } + } + + if (count($emails) > 0) { + $date = Carbon::parse($upgrade->activation_date)->format('d/m/Y'); + + $subject = 'Casper Protocol Upgrade Available - Upgrade before ' . $date; + $content = 'Version ' . $upgrade->version . ' of the Casper protocol is available and must be installed prior to ' . $date . '. '; + $content .= 'This version goes live on mainnet in ERA #' . $upgrade->activation_era . '. '; + $content .= 'If you have already completed this upgrade, please click "Mark as Done" in the Upgrades tab of your Casper Membership Portal.'; + $content .= '

This upgrade can be found at ' . $upgrade->link . '.

'; + $content .= 'Changes include:
' . $upgrade->notes . '.'; + + foreach ($emails as $email) { + Mail::to($email)->send(new UserAlert($subject, $content)); + } + } + } +} \ No newline at end of file diff --git a/app/Jobs/PerkNotification.php b/app/Jobs/PerkNotification.php new file mode 100644 index 00000000..a548dbac --- /dev/null +++ b/app/Jobs/PerkNotification.php @@ -0,0 +1,48 @@ +perk = $perk; + } + + public function handle() { + $members = Helper::getActiveMembers(); + if ($members && count($members) > 0) { + $emails = []; + foreach ($members as $member) { + $email = $member->email; + if (!in_array($email, $emails)) { + $emails[] = $email; + } + } + if (count($emails) > 0) { + $extraOptions = [ + 'perk_title' => $this->perk->title ?? '' + ]; + $emailerData = EmailerHelper::getEmailerData(); + foreach ($emails as $email) { + $user = new \stdClass(); + $user->email = $email; + EmailerHelper::triggerUserEmail($email, 'New Perk Created', $emailerData, $user, null, $extraOptions); + } + } + } + } +} diff --git a/app/Jobs/TestJob.php b/app/Jobs/TestJob.php new file mode 100644 index 00000000..12d70803 --- /dev/null +++ b/app/Jobs/TestJob.php @@ -0,0 +1,35 @@ +upgrade = $upgrade; + } + + /** + * Execute the job. + * + * @return void + */ + public function handle() + { + if (!$this->upgrade) return; + + $upgrade = $this->upgrade; + $emails = []; + + // Fetch Valid Users + $users = User::select('email') + ->has('addresses') + ->where('banned', 0) + ->where('role', 'member') + ->whereNotNull('public_address_node') + ->whereNotNull('signature_request_id') + ->whereNotNull('signed_file') + ->whereNotNull('node_verified_at') + ->whereNotNull('letter_file') + ->whereNotNull('letter_verified_at') + ->where(function ($query) { + $query->doesntHave('profile') + ->orWhereHas('profile', function ($query2) { + $query2->where('profile.extra_status', '!=', 'Suspended') + ->orWhereNull('profile.extra_status'); + }); + }) + ->get(); + if ($users && count($users) > 0) { + foreach ($users as $user) { + $email = $user->email; + if (!in_array($email, $emails)) { + $emails[] = $email; + } + } + } + + if (count($emails) > 0) { + $date = Carbon::parse($upgrade->activation_date)->format('d/m/Y'); + + $subject = 'Casper Protocol Upgrade Available - Upgrade before tomorrow'; + $content = 'Version ' . $upgrade->version . ' of the Casper protocol is available and must be installed prior to ' . $date . '. '; + $content .= 'This version goes live on mainnet in ERA #' . $upgrade->activation_era . '. '; + $content .= 'If you have already completed this upgrade, please click "Mark as Done" in the Upgrades tab of your Casper Membership Portal.'; + $content .= '

This upgrade can be found at ' . $upgrade->link . '.

'; + $content .= 'Changes include:
' . $upgrade->notes . '.'; + + foreach ($emails as $email) { + Mail::to($email)->send(new UserAlert($subject, $content)); + } + } + + $upgrade->reminder_24_sent = true; + $upgrade->save(); + } +} \ No newline at end of file diff --git a/app/Models/AllNodeData2.php b/app/Models/AllNodeData2.php new file mode 100644 index 00000000..af34815c --- /dev/null +++ b/app/Models/AllNodeData2.php @@ -0,0 +1,12 @@ +belongsTo('App\Models\User', 'user_id', 'id'); diff --git a/app/Models/Discussion.php b/app/Models/Discussion.php index c0e06bb7..bb4f18c7 100644 --- a/app/Models/Discussion.php +++ b/app/Models/Discussion.php @@ -31,8 +31,8 @@ public function getIsNewAttribute() 'user_id' => $user->id, 'discussion_id' => $this->id ])->first() == null; - $notOld = Carbon::now()->diffInDays(Carbon::parse($this->created_at)) < 3; - return $notOld && $notRemoved; + $notOld = Carbon::now('UTC')->diffInDays(Carbon::parse($this->created_at)) < 3; + return $notOld && $notRemoved; } public function getTotalPinnedAttribute() diff --git a/app/Models/Profile.php b/app/Models/Profile.php index 280065fb..4b1cd764 100644 --- a/app/Models/Profile.php +++ b/app/Models/Profile.php @@ -18,4 +18,9 @@ public function getDocumentVerifiedAtAttribute($value) } return null; } + + public function user() + { + return $this->hasOne('App\Models\User', 'id', 'user_id'); + } } diff --git a/app/Models/ReinstatementHistory.php b/app/Models/ReinstatementHistory.php new file mode 100644 index 00000000..434ef07c --- /dev/null +++ b/app/Models/ReinstatementHistory.php @@ -0,0 +1,17 @@ +hasOne('App\Models\User', 'id', 'user_id'); + } +} diff --git a/app/Models/Upgrade.php b/app/Models/Upgrade.php new file mode 100644 index 00000000..4c19a0b8 --- /dev/null +++ b/app/Models/Upgrade.php @@ -0,0 +1,11 @@ + $this->id])->pluck('discussion_id'); $count = Discussion::whereNotIn('id', $removedNews) - ->whereDate('created_at', '>', Carbon::now()->subDays(3)) + ->whereDate('created_at', '>', Carbon::now('UTC')->subDays(3)) ->count(); return $count; } diff --git a/app/Models/VerifyUser.php b/app/Models/VerifyUser.php index 59ea1e3b..4b649a85 100644 --- a/app/Models/VerifyUser.php +++ b/app/Models/VerifyUser.php @@ -9,19 +9,19 @@ class VerifyUser extends Model { use HasFactory; - const TOKEN_LIFETIME = 300; - const TYPE_VERIFY_EMAIL= 'verify_email'; - const TYPE_RESET_PASSWORD= 'reset_password'; - const TYPE_CANCEL_EMAIL= 'cancel_email'; - const TYPE_CONFIRM_EMAIL= 'confirm_email'; - const TYPE_LOGIN_TWO_FA= 'login_twoFA'; - const TYPE_INVITE_ADMIN= 'invite_admin'; + const TOKEN_LIFETIME = 300; + const TYPE_VERIFY_EMAIL = 'verify_email'; + const TYPE_RESET_PASSWORD = 'reset_password'; + const TYPE_CANCEL_EMAIL = 'cancel_email'; + const TYPE_CONFIRM_EMAIL = 'confirm_email'; + const TYPE_LOGIN_TWO_FA = 'login_twoFA'; + const TYPE_INVITE_ADMIN = 'invite_admin'; - public $timestamps = false; - public $primaryKey = 'email'; - public $keyType = 'string'; + public $timestamps = false; + public $primaryKey = 'email'; + public $keyType = 'string'; - protected $table = 'verify_user'; + protected $table = 'verify_user'; /** * The attributes that are mass assignable. diff --git a/app/Providers/HorizonServiceProvider.php b/app/Providers/HorizonServiceProvider.php new file mode 100644 index 00000000..08881175 --- /dev/null +++ b/app/Providers/HorizonServiceProvider.php @@ -0,0 +1,42 @@ +email, [ + // + ]); + }); + } +} diff --git a/app/Repositories/Base/BaseRepository.php b/app/Repositories/Base/BaseRepository.php index 04f700b3..98e1f27d 100644 --- a/app/Repositories/Base/BaseRepository.php +++ b/app/Repositories/Base/BaseRepository.php @@ -1,13 +1,10 @@ model->updateOrCreate($attributes, $values); @@ -128,7 +125,7 @@ public function firstOrFail(array $where, $attributes = ['*']) * * @return static */ - public function updateOrCreateWithTrashed(array $attributes, array $values = array()) + public function updateOrCreateWithTrashed(array $attributes, array $values = []) { try { return $this->model->withTrashed()->updateOrCreate($attributes, $values); @@ -172,7 +169,7 @@ public function deleteConditions(array $where) } } - public function firstOrCreate(array $attributes, array $values = array()) + public function firstOrCreate(array $attributes, array $values = []) { try { return $this->model->firstOrCreate($attributes, $values); @@ -180,4 +177,4 @@ public function firstOrCreate(array $attributes, array $values = array()) throw $e; } } -} +} \ No newline at end of file diff --git a/app/Services/ChecksumValidator.php b/app/Services/ChecksumValidator.php index 4c523159..0a23691f 100644 --- a/app/Services/ChecksumValidator.php +++ b/app/Services/ChecksumValidator.php @@ -14,11 +14,11 @@ function __construct($vid = null) { $this->validator_id = $vid; } - $this->HEX_CHARS = array( + $this->HEX_CHARS = [ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f', 'A', 'B', 'C', 'D', 'E', 'F' - ); + ]; $this->SMALL_BYTES_COUNT = 75; } @@ -30,7 +30,7 @@ function _blake_hash($public_key) { } function _bytes_to_nibbles($v) { - $output_nibbles = array(); + $output_nibbles = []; foreach(str_split($v) as $byte) { $byte = ord($byte); @@ -43,7 +43,7 @@ function _bytes_to_nibbles($v) { function _bytes_to_bits_cycle($v) { $_blake_hash = $this->_blake_hash($v); - $ret = array(); + $ret = []; foreach(str_split($_blake_hash) as $b) { $b = ord($b); @@ -59,7 +59,7 @@ function _bytes_to_bits_cycle($v) { function _encode($public_key) { $nibbles = $this->_bytes_to_nibbles($public_key); $hash_bits = $this->_bytes_to_bits_cycle($public_key); - $ret = array(); + $ret = []; $k = 0; foreach($nibbles as $nibble) { diff --git a/app/Services/NodeHelper.php b/app/Services/NodeHelper.php index f85882b9..0c608989 100644 --- a/app/Services/NodeHelper.php +++ b/app/Services/NodeHelper.php @@ -36,36 +36,19 @@ public function __construct() // do nothing } - public function decodePeers($__peers) - { - $decoded_peers = array(); - if($__peers && gettype($__peers) == 'array') { - foreach($__peers as $__peer) { - $address = $__peer['address'] ?? ''; - $address = explode(':', $address)[0]; - - if($address) { - $decoded_peers[] = $address; - } - } - } - return $decoded_peers; - } - public function retrieveGlobalUptime($this_era_id) { - $total_data = array(); + $total_data = []; $event_store_url = 'https://event-store-api-clarity-mainnet.make.services/relative-average-validator-performances?limit=100&page=1&era_id='.(string)($this_era_id - 1); - // make initial request, get response $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $event_store_url); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); $json = curl_exec($ch); - if(curl_errno($ch)) { - return array(); + if (curl_errno($ch)) { + return []; } try { @@ -74,25 +57,22 @@ public function retrieveGlobalUptime($this_era_id) $object = (object)[]; } - // get total pages - $page_count = (int)($object->pageCount ?? 0); - + $page_count = (int) ($object->pageCount ?? 0); // update total data object - $data = $object->data ?? array(); + $data = $object->data ?? []; $total_data = array_merge($total_data, $data); - // iterate through remaining pages - for($i = 0; $i < $page_count; $i++) { - if($i != 0) { + for ($i = 0; $i < $page_count; $i++) { + if ($i != 0) { $j = $i + 1; $event_store_url = 'https://event-store-api-clarity-mainnet.make.services/relative-average-validator-performances?limit=100&page='.$j.'&era_id='.(string)($this_era_id - 1); curl_setopt($ch, CURLOPT_URL, $event_store_url); $json = curl_exec($ch); - if(curl_errno($ch)) { + if (curl_errno($ch)) { continue; } @@ -102,9 +82,8 @@ public function retrieveGlobalUptime($this_era_id) $object = (object)[]; } - // update total data object - $data = $object->data ?? array(); + $data = $object->data ?? []; $total_data = array_merge($total_data, $data); } sleep(1); @@ -114,570 +93,17 @@ public function retrieveGlobalUptime($this_era_id) return $total_data; } - - public function discoverPeers() - { - $port8888_responses = array(); - $http_protocol = 'http://'; - $status_port = ':8888/status'; - - - // Get peers from trusted node, port 8888 - $curl = curl_init(); - curl_setopt($curl, CURLOPT_URL, $http_protocol.getenv('NODE_IP').$status_port); - curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1); - curl_setopt($curl, CURLOPT_CONNECTTIMEOUT, 15); - curl_setopt($curl, CURLOPT_TIMEOUT, 15); - - // try once with main NODE_IP - $json = curl_exec($curl); - - if(curl_errno($curl) && getenv('BACKUP_NODE_IP')) { - curl_setopt($curl, CURLOPT_URL, $http_protocol.getenv('BACKUP_NODE_IP').$status_port); - - // try twice with main BACKUP_NODE_IP - $json = curl_exec($curl); - - if(curl_errno($curl)) { - return array(); - } - } - - curl_close($curl); - - try { - $object = json_decode($json, true); - } catch(Exception $e) { - $object = array(); - } - - - // configure peers object - $peers = $object['peers'] ?? array(); - unset($object['peers']); - $port8888_responses[] = $object; - $peers = $this->decodePeers($peers); - $peers = array_unique($peers); - $peers = array_values($peers); - - if(!$peers || empty($peers)) { - return array(); - } - - - // save peer count for trusted node - $port8888_responses[0]['peer_count'] = count($peers); - - - // divide up chunks for multi curl handler - if(count($peers) >= 20) { - $divided = (int)(count($peers) / 20); - } else { - $divided = 1; - } - - $remainder = count($peers) % 20; - $real_index = 0; - info('Requesting peers.. Total: '.count($peers)); - - - // multi curl handler each full chunk - for($chunk = 0; $chunk < $divided; $chunk++) { - $mh = curl_multi_init(); - $ch = array(); - - for($i = 0; $i < 20; $i++) { - $ch[$i] = curl_init(); - curl_setopt($ch[$i], CURLOPT_URL, $http_protocol.$peers[$real_index].$status_port); - curl_setopt($ch[$i], CURLOPT_HEADER, 0); - curl_setopt($ch[$i], CURLOPT_RETURNTRANSFER, 1); - curl_setopt($ch[$i], CURLOPT_CONNECTTIMEOUT, 15); - curl_setopt($ch[$i], CURLOPT_TIMEOUT, 15); - - curl_multi_add_handle($mh, $ch[$i]); - $real_index += 1; - } - - - //execute chunk multi handle for this chunk - do { - $status = curl_multi_exec($mh, $active); - - if($active) { - curl_multi_select($mh); - } - } while($active && $status == CURLM_OK); - - for($i = 0; $i < 20; $i++) { - curl_multi_remove_handle($mh, $ch[$i]); - } - - foreach($ch as $req) { - $content = curl_multi_getcontent($req); - - if($content) { - $object = json_decode($content, true); - $peer_count = isset($object['peers']) ? count($object['peers']) : 0; - unset($object['peers']); - $object['peer_count'] = $peer_count; - $port8888_responses[] = $object; - } - } - - curl_multi_close($mh); - $mh = null; - usleep(50000); - } - - - // do last chunk - $mh = curl_multi_init(); - $ch = array(); - - for ($i = 0; $i < $remainder; $i++) { - $ch[$i] = curl_init(); - curl_setopt($ch[$i], CURLOPT_URL, $http_protocol.$peers[$real_index].$status_port); - curl_setopt($ch[$i], CURLOPT_HEADER, 0); - curl_setopt($ch[$i], CURLOPT_RETURNTRANSFER, 1); - curl_setopt($ch[$i], CURLOPT_CONNECTTIMEOUT, 15); - curl_setopt($ch[$i], CURLOPT_TIMEOUT, 15); - - curl_multi_add_handle($mh, $ch[$i]); - $real_index += 1; - } - - - //execute chunk multi handle for last chunk - do { - $status = curl_multi_exec($mh, $active); - - if ($active) { - curl_multi_select($mh); - } - } while ($active && $status == CURLM_OK); - - for($i = 0; $i < $remainder; $i++) { - curl_multi_remove_handle($mh, $ch[$i]); - } - - foreach ($ch as $req) { - $content = curl_multi_getcontent($req); - - if ($content) { - $object = json_decode($content, true); - $peer_count = isset($object['peers']) ? count($object['peers']) : 0; - unset($object['peers']); - $object['peer_count'] = $peer_count; - $port8888_responses[] = $object; - } - } - - info('Closing multi handle for the last chunk..done'); - curl_multi_close($mh); - $mh = null; - - return $port8888_responses; - } - - public function getValidAddresses() - { - $curl = curl_init(); - $json_data = [ - 'id' => (int) time(), - 'jsonrpc' => '2.0', - 'method' => 'state_get_auction_info', - 'params' => array() - ]; - - curl_setopt($curl, CURLOPT_URL, 'http://' . getenv('NODE_IP') . ':7777/rpc'); - curl_setopt($curl, CURLOPT_POST, true); - curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); - curl_setopt($curl, CURLOPT_CONNECTTIMEOUT, 15); - curl_setopt($curl, CURLOPT_TIMEOUT, 15); - curl_setopt($curl, CURLOPT_POSTFIELDS, json_encode($json_data)); - curl_setopt($curl, CURLOPT_HTTPHEADER, [ - 'Accept: application/json', - 'Content-type: application/json', - ]); - - // parse response for bids from NODE_IP - $response = curl_exec($curl); - - if (curl_errno($curl) && getenv('BACKUP_NODE_IP')) { - curl_setopt($curl, CURLOPT_URL, 'http://' . getenv('BACKUP_NODE_IP') . ':7777/rpc'); - - // try twice with BACKUP_NODE_IP - $response = curl_exec($curl); - } - - curl_close($curl); - $decodedResponse = json_decode($response, true); - $auction_state = $decodedResponse['result']['auction_state'] ?? []; - $bids = $auction_state['bids'] ?? []; - - $addresses = []; - if ($bids) { - foreach($bids as $bid) { - if (isset($bid['public_key']) && $bid['public_key']) { - $public_key = strtolower($bid['public_key']); - $addresses[] = $public_key; - } - } - } - return $addresses; - } - - public function getValidatorStanding() - { - // get node ips from peers - $port8888_responses = $this->discoverPeers(); - - // get auction state from trusted node RPC - $curl = curl_init(); - - $json_data = array( - 'id' => (int) time(), - 'jsonrpc' => '2.0', - 'method' => 'state_get_auction_info', - 'params' => array() - ); - - curl_setopt($curl, CURLOPT_URL, 'http://' . getenv('NODE_IP') . ':7777/rpc'); - curl_setopt($curl, CURLOPT_POST, true); - curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); - curl_setopt($curl, CURLOPT_CONNECTTIMEOUT, 15); - curl_setopt($curl, CURLOPT_TIMEOUT, 15); - curl_setopt($curl, CURLOPT_POSTFIELDS, json_encode($json_data)); - curl_setopt($curl, CURLOPT_HTTPHEADER, array( - 'Accept: application/json', - 'Content-type: application/json', - )); - - // parse response for bids - $response = curl_exec($curl); - - if (curl_errno($curl) && getenv('BACKUP_NODE_IP')) { - curl_setopt($curl, CURLOPT_URL, 'http://' . getenv('BACKUP_NODE_IP') . ':7777/rpc'); - - // try twice with BACKUP_NODE_IP - $response = curl_exec($curl); - } - - curl_close($curl); - $decodedResponse = json_decode($response, true); - $auction_state = $decodedResponse['result']['auction_state'] ?? array(); - $bids = $auction_state['bids'] ?? array(); - - // get era ID - $era_id = (int)($auction_state['era_validators'][0]['era_id'] ?? 0); - - // set MBS array. minimum bid slot amount - $MBS_arr = array(); - - // set default object - $global_validator_standing = array( - "global_block_height" => 0, - "global_build_version" => '1.0.0', - "global_chainspec_name" => 'casper', - "validator_standing" => array() - ); - - // check each bid validator against existing platform validators - if($bids) { - // get global uptimes from MAKE - $global_uptime = $this->retrieveGlobalUptime($era_id); - - foreach($bids as $bid) { - $public_key = strtolower($bid['public_key'] ?? 'nill'); - $node_info = UserAddress::where('public_address_node', $public_key)->first(); - - // parse bid - $b = $bid['bid'] ?? array(); - - // get self stake amount - $self_staked_amount = (int)($b['staked_amount'] ?? 0); - - // calculate total stake, delegators + self stake - $delegators = (array)($b['delegators'] ?? array()); - $delegators_count = count($delegators); - $total_staked_amount = 0 + $self_staked_amount; - - foreach($delegators as $delegator) { - $staked_amount = (int)($delegator['staked_amount'] ?? 0); - $total_staked_amount += $staked_amount; - } - - $total_staked_amount = $total_staked_amount / 1000000000; - $self_staked_amount = $self_staked_amount / 1000000000; - - // append to MBS array and pluck 100th place later - $MBS_arr[$public_key] = $total_staked_amount; - - // node exists on platform, fetch/save info - if($node_info) { - // get delegation rate - $delegation_rate = (float)($b['delegation_rate'] ?? 0); - - // get active status (equivocation check) - $inactive = (bool)($b['inactive'] ?? false); - - // save current stake amount to daily earnings table - $earning = new DailyEarning(); - $earning->node_address = $public_key; - $earning->self_staked_amount = (int)$self_staked_amount; - $earning->created_at = Carbon::now('UTC'); - $earning->save(); - - // get difference between current self stake and yesterdays self stake - $get_earning = DailyEarning::where('node_address', $public_key) - ->where('created_at', '>', Carbon::now('UTC')->subHours(24)) - ->orderBy('created_at', 'asc') - ->first(); - $yesterdays_self_staked_amount = (float)($get_earning->self_staked_amount ?? 0); - $daily_earning = $self_staked_amount - $yesterdays_self_staked_amount; - - // get node uptime from MAKE object - $uptime = 0; - - foreach($global_uptime as $uptime_array) { - $fvid = strtolower($uptime_array->public_key ?? ''); - - if($fvid == $public_key) { - $uptime = (float)($uptime_array->average_score ?? 1); - break; - } - } - - $float_uptime = (float)($uptime / 100.0); - - // build individual validator_standing object - $global_validator_standing - ['validator_standing'] - [$public_key] - ["delegators_count"] = $delegators_count; - - $global_validator_standing - ['validator_standing'] - [$public_key] - ["total_staked_amount"] = $total_staked_amount; - - $global_validator_standing - ['validator_standing'] - [$public_key] - ["self_staked_amount"] = $self_staked_amount; - - $global_validator_standing - ['validator_standing'] - [$public_key] - ["delegation_rate"] = $delegation_rate; - - $global_validator_standing - ['validator_standing'] - [$public_key] - ["uptime"] = $float_uptime; - - $global_validator_standing - ['validator_standing'] - [$public_key] - ["update_responsiveness"] = 1; - - $global_validator_standing - ['validator_standing'] - [$public_key] - ["daily_earning"] = $daily_earning; - - $global_validator_standing - ['validator_standing'] - [$public_key] - ["inactive"] = $inactive; - - - // look for existing peer by public key for port 8888 data - foreach($port8888_responses as $port8888data) { - $our_public_signing_key = strtolower($port8888data['our_public_signing_key'] ?? ''); - - if($our_public_signing_key == $public_key) { - // found in peers - $peer_count = (int)($port8888data['peer_count'] ?? 0); - $block_height = (int)($port8888data['last_added_block_info']['height'] ?? 0); - $build_version = $port8888data['build_version'] ?? '1.0.0'; - $chainspec_name = $port8888data['chainspec_name'] ?? 'casper'; - - if($block_height > $global_validator_standing["global_block_height"]) { - $global_validator_standing["global_block_height"] = $block_height; - } - - if($build_version > $global_validator_standing["global_build_version"]) { - $global_validator_standing["global_build_version"] = $build_version; - } - - - // apply to global_validator_standing - $global_validator_standing - ['validator_standing'] - [$public_key] - ["block_height"] = $block_height; - - $global_validator_standing - ['validator_standing'] - [$public_key] - ["build_version"] = $build_version; - - $global_validator_standing - ['validator_standing'] - [$public_key] - ["chainspec_name"] = $chainspec_name; - - $global_validator_standing - ['validator_standing'] - [$public_key] - ["peer_count"] = $peer_count; - - break; - } - } - } - } - } - - // find MBS - rsort($MBS_arr); - $MBS = null; - if (count($MBS_arr) > 0) $MBS = $MBS_arr[99] ?? $MBS_arr[count($MBS_arr) - 1]; - $global_validator_standing['MBS'] = $MBS; - - // DailyEarning garbage cleanup - DailyEarning::where('created_at', '<', Carbon::now('UTC')->subDays(90))->delete(); - - return $global_validator_standing; - } - - public function getTotalRewards($validatorId) - { - $response = Http::withOptions([ - 'verify' => false, - ])->get("https://api.CSPR.live/validators/$validatorId/total-rewards"); - return $response->json(); - } - - public function updateStats() - { - $data = $this->getValidatorStanding(); - $mbs = $data['MBS'] ?? 0; - $peers = $data['peers'] ?? 0; - $users = User::with('addresses')->whereNotNull('public_address_node')->get(); - $validator_standing = $data['validator_standing'] ?? null; - $setting = Setting::where('name', 'peers')->first(); - - if (!$setting) { - $setting = new Setting; - $setting->name = 'peers'; - $setting->value = ''; - $setting->save(); - } - - $setting->value = $peers; - $setting->save(); - - if ($validator_standing) { - // Refresh Validator Standing - foreach ($validator_standing as $key => $value) { - $validator_standing[strtolower($key)] = $value; - } - - foreach ($users as $user) { - if (isset($user->addresses) && count($user->addresses) > 0) { - $addresses = $user->addresses; - $userAddress = strtolower($user->public_address_node); - foreach ($addresses as $address) { - $validatorid = strtolower($address->public_address_node); - - if (isset($validator_standing[$validatorid])) { - $info = $validator_standing[$validatorid]; - $fee = (float) $info['delegation_rate']; - - if ($userAddress == $validatorid) { - $user->pending_node = 0; - $user->validator_fee = round($fee, 2); - $user->save(); - } - - $address->pending_node = 0; - $address->validator_fee = round($fee, 2); - $address->save(); - - $totalRewards = $this->getTotalRewards($validatorid); - - $build_version = $info['build_version'] ?? null; - - if ($build_version) { - $build_version = explode('-', $build_version); - $build_version = $build_version[0]; - } - - if( - isset($info['block_height']) && - isset($info['peer_count']) - ) { - $is_open_port = 1; - } else { - $is_open_port = 0; - } - - $inactive = (bool)($info['inactive'] ?? false); - $inactive = $inactive ? 1 : 0; - - NodeInfo::updateOrCreate( - [ - 'node_address' => $validatorid - ], - [ - 'delegators_count' => $info['delegators_count'] ?? 0, - 'total_staked_amount' => $info['total_staked_amount'], - 'delegation_rate' => $info['delegation_rate'], - 'daily_earning' => $info['daily_earning'] ?? 0, - 'self_staked_amount' => $info['self_staked_amount'] ?? 0, - 'total_earning' => isset($totalRewards['data']) && $totalRewards['data'] > 0 ? $totalRewards['data'] / 1000000000 : 0, - 'is_open_port' => $is_open_port, - 'mbs' => $mbs, - 'update_responsiveness' => isset($info['update_responsiveness']) ? $info['update_responsiveness'] * 100 : 0, - 'uptime' => isset($info['uptime']) ? $info['uptime'] * 100 : 0, - 'block_height' => $info['block_height'] ?? 0, - 'peers' => $info['peer_count'] ?? 0, - 'inactive' => $inactive - ] - ); - - Node::updateOrCreate( - [ - 'node_address' => $validatorid - ], - [ - 'block_height' => $info['block_height'] ?? null, - 'protocol_version' => $build_version, - 'update_responsiveness' => isset($info['update_responsiveness']) ? $info['update_responsiveness'] * 100 : null, - 'uptime' => isset($info['uptime']) ? $info['uptime'] : null, - 'weight' => $info['daily_earnings'] ?? 0, - 'peers' => $info['peer_count'] ?? 0, - ] - ); - } - } - } - } - } - } - + public function getValidatorRewards($validatorId, $_range) { - $nowtime = (int)time(); + $nowtime = (int) time(); $range = 0; $days = 30; - $leap_year = (int)date('Y'); + $leap_year = (int) date('Y'); $leap_days = $leap_year % 4 == 0 ? 29 : 28; - $month = (int)date('m'); + $month = (int) date('m'); - switch($month) { + switch ($month) { case 1: $days = 31; break; @@ -718,46 +144,53 @@ public function getValidatorRewards($validatorId, $_range) break; } - switch($_range) { + switch ($_range) { case 'day': $range = $nowtime - 86400; - break; + break; case 'week': $range = $nowtime - (86400 * 7); - break; + break; case 'month': $range = $nowtime - (86400 * $days); - break; + break; case 'year': $range = $nowtime - (86400 * (365 + ($leap_days % 2))); - break; + break; default: return false; - break; + break; } $timestamp = Carbon::createFromTimestamp($range, 'UTC')->toDateTimeString(); - $total_records = DailyEarning::where('node_address', $validatorId) - ->where('created_at', '>', $timestamp) - ->get(); - - $new_array = array(); + // $total_records = DailyEarning::where('node_address', $validatorId) + // ->where('created_at', '>', $timestamp) + // ->get(); + + $total_records = DB::select(" + SELECT bid_self_staked_amount, created_at + FROM all_node_data2 + WHERE created_at > '$timestamp' + AND public_key = '$validatorId' + "); + + $new_array = []; $display_record_count = 100; - if($total_records) { + if ($total_records) { $modded = count($total_records) % $display_record_count; $numerator = count($total_records) - $modded; $modulo = $numerator / $display_record_count; - $new_array = array(); + $new_array = []; $i = $modulo; - if($modulo == 0) { + if ((int)$modulo == 0) { $modulo = 1; } - foreach($total_records as $record) { - if($i % $modulo == 0) { - $new_array[(string)strtotime($record->created_at.' UTC')] = (string)$record->self_staked_amount; + foreach ($total_records as $record) { + if ($i % $modulo == 0) { + $new_array[(string) strtotime($record->created_at.' UTC')] = (string) $record->bid_self_staked_amount; } $i++; } diff --git a/app/Services/ShuftiproCheck.php b/app/Services/ShuftiproCheck.php index ca03d253..a722265c 100644 --- a/app/Services/ShuftiproCheck.php +++ b/app/Services/ShuftiproCheck.php @@ -2,6 +2,8 @@ namespace App\Services; +use Carbon\Carbon; + use App\Models\Profile; use App\Models\Shuftipro; use App\Models\ShuftiproTemp; @@ -153,7 +155,7 @@ public function handleExisting($item) { $record->reviewed = $is_successful ? 1 : 0; // No need to review successful ones if ($status == 'approved') { - $record->manual_approved_at = now(); + $record->manual_approved_at = Carbon::now('UTC'); } if ($document_proof) { $record->document_proof = $document_proof; @@ -173,8 +175,8 @@ public function handleExisting($item) { $user = User::find($user_id); if ($user) { - $user->kyc_verified_at = now(); - $user->approve_at = now(); + $user->kyc_verified_at = Carbon::now('UTC'); + $user->approve_at = Carbon::now('UTC'); $user->save(); Mail::to($user->email)->send(new KYCApproved); @@ -354,8 +356,8 @@ public function handle($item) $user = User::find($user_id); if ($user) { - $user->kyc_verified_at = now(); - $user->approve_at = now(); + $user->kyc_verified_at = Carbon::now('UTC'); + $user->approve_at = Carbon::now('UTC'); $user->save(); Mail::to($user->email)->send(new KYCApproved); diff --git a/composer.json b/composer.json index 5d099e31..5a266bee 100644 --- a/composer.json +++ b/composer.json @@ -13,11 +13,13 @@ "guzzlehttp/guzzle": "^7.4.3", "hellosign/hellosign-php-sdk": "^3.7", "laravel/framework": "^8.40", + "laravel/horizon": "^5.10", "laravel/passport": "^10.1", "laravel/tinker": "^2.5", + "make-software/casper-php-sdk": "dev-master", "phpseclib/phpseclib": "~3.0", - "stripe/stripe-php": "^7.121", - "make-software/casper-php-sdk": "dev-master" + "predis/predis": "^2.0", + "stripe/stripe-php": "^7.121" }, "require-dev": { "facade/ignition": "^2.5", @@ -33,9 +35,7 @@ "Database\\Factories\\": "database/factories/", "Database\\Seeders\\": "database/seeders/" }, - "files": [ - "app/Helpers/helper.php" - ] + "files": [] }, "autoload-dev": { "psr-4": { diff --git a/config/app.php b/config/app.php index f9034603..6c4bde74 100644 --- a/config/app.php +++ b/config/app.php @@ -175,6 +175,7 @@ App\Providers\AuthServiceProvider::class, // App\Providers\BroadcastServiceProvider::class, App\Providers\EventServiceProvider::class, + App\Providers\HorizonServiceProvider::class, App\Providers\RouteServiceProvider::class, ], diff --git a/config/horizon.php b/config/horizon.php new file mode 100644 index 00000000..01a95229 --- /dev/null +++ b/config/horizon.php @@ -0,0 +1,230 @@ + env('HORIZON_DOMAIN'), + + /* + |-------------------------------------------------------------------------- + | Horizon Path + |-------------------------------------------------------------------------- + | + | This is the URI path where Horizon will be accessible from. Feel free + | to change this path to anything you like. Note that the URI will not + | affect the paths of its internal API that aren't exposed to users. + | + */ + + 'path' => env('HORIZON_PATH', 'horizon'), + + /* + |-------------------------------------------------------------------------- + | Horizon Redis Connection + |-------------------------------------------------------------------------- + | + | This is the name of the Redis connection where Horizon will store the + | meta information required for it to function. It includes the list + | of supervisors, failed jobs, job metrics, and other information. + | + */ + + 'use' => 'default', + + /* + |-------------------------------------------------------------------------- + | Horizon Redis Prefix + |-------------------------------------------------------------------------- + | + | This prefix will be used when storing all Horizon data in Redis. You + | may modify the prefix when you are running multiple installations + | of Horizon on the same server so that they don't have problems. + | + */ + + 'prefix' => env( + 'HORIZON_PREFIX', + Str::slug(env('APP_NAME', 'laravel'), '_').'_horizon:' + ), + + /* + |-------------------------------------------------------------------------- + | Horizon Route Middleware + |-------------------------------------------------------------------------- + | + | These middleware will get attached onto each Horizon route, giving you + | the chance to add your own middleware to this list or change any of + | the existing middleware. Or, you can simply stick with this list. + | + */ + + 'middleware' => ['web'], + + /* + |-------------------------------------------------------------------------- + | Queue Wait Time Thresholds + |-------------------------------------------------------------------------- + | + | This option allows you to configure when the LongWaitDetected event + | will be fired. Every connection / queue combination may have its + | own, unique threshold (in seconds) before this event is fired. + | + */ + + 'waits' => [ + 'redis:default' => 60, + ], + + /* + |-------------------------------------------------------------------------- + | Job Trimming Times + |-------------------------------------------------------------------------- + | + | Here you can configure for how long (in minutes) you desire Horizon to + | persist the recent and failed jobs. Typically, recent jobs are kept + | for one hour while all failed jobs are stored for an entire week. + | + */ + + 'trim' => [ + 'recent' => 60, + 'pending' => 60, + 'completed' => 60, + 'recent_failed' => 10080, + 'failed' => 10080, + 'monitored' => 10080, + ], + + /* + |-------------------------------------------------------------------------- + | Metrics + |-------------------------------------------------------------------------- + | + | Here you can configure how many snapshots should be kept to display in + | the metrics graph. This will get used in combination with Horizon's + | `horizon:snapshot` schedule to define how long to retain metrics. + | + */ + + 'metrics' => [ + 'trim_snapshots' => [ + 'job' => 24, + 'queue' => 24, + ], + ], + + /* + |-------------------------------------------------------------------------- + | Fast Termination + |-------------------------------------------------------------------------- + | + | When this option is enabled, Horizon's "terminate" command will not + | wait on all of the workers to terminate unless the --wait option + | is provided. Fast termination can shorten deployment delay by + | allowing a new instance of Horizon to start while the last + | instance will continue to terminate each of its workers. + | + */ + + 'fast_termination' => false, + + /* + |-------------------------------------------------------------------------- + | Memory Limit (MB) + |-------------------------------------------------------------------------- + | + | This value describes the maximum amount of memory the Horizon master + | supervisor may consume before it is terminated and restarted. For + | configuring these limits on your workers, see the next section. + | + */ + + 'memory_limit' => 64, + + /* + |-------------------------------------------------------------------------- + | Queue Worker Configuration + |-------------------------------------------------------------------------- + | + | Here you may define the queue worker settings used by your application + | in all environments. These supervisors and settings handle all your + | queued jobs and will be provisioned by Horizon during deployment. + | + */ + + 'defaults' => [ + 'supervisor-1' => [ + 'connection' => 'redis', + 'queue' => ['default'], + // 'balance' => 'auto', + 'balance' => 'simple', + 'balanceMaxShift' => 1, + 'balanceCooldown' => 3, + 'maxTime' => 0, + 'maxJobs' => 0, + 'memory' => 128, + 'tries' => 1, + 'timeout' => 60, + 'nice' => 0, + ], + 'supervisor-long-running' => [ + 'connection' => 'redis-long-running', + 'queue' => ['default_long'], + 'balance' => 'simple', + 'balanceMaxShift' => 1, + 'balanceCooldown' => 3, + 'maxTime' => 0, + 'maxJobs' => 0, + 'memory' => 128, + 'tries' => 1, + 'timeout' => 3600 + ], + ], + + 'environments' => [ + 'production' => [ + 'supervisor-1' => [ + 'maxProcesses' => 10, + 'processes' => 10 + ], + 'supervisor-long-running' => [ + 'maxProcesses' => 10, + 'processes' => 10 + ] + ], + + 'staging' => [ + 'supervisor-1' => [ + 'maxProcesses' => 10, + 'processes' => 10 + ], + 'supervisor-long-running' => [ + 'maxProcesses' => 5, + 'processes' => 5 + ] + ], + + 'local' => [ + 'supervisor-1' => [ + 'maxProcesses' => 3, + 'processes' => 3 + ], + 'supervisor-long-running' => [ + 'maxProcesses' => 1, + 'processes' => 1 + ] + ], + ], +]; diff --git a/config/queue.php b/config/queue.php index 25ea5a81..2c966f86 100644 --- a/config/queue.php +++ b/config/queue.php @@ -70,7 +70,15 @@ 'block_for' => null, 'after_commit' => false, ], - + + 'redis-long-running' => [ + 'driver' => 'redis', + 'connection' => 'default', + 'queue' => 'default_long', + 'retry_after' => 3800, + 'block_for' => null, + 'after_commit' => false, + ], ], /* diff --git a/config/session.php b/config/session.php index ac0802b1..e4e4eec3 100644 --- a/config/session.php +++ b/config/session.php @@ -168,7 +168,7 @@ | */ - 'secure' => env('SESSION_SECURE_COOKIE'), + 'secure' => true, /* |-------------------------------------------------------------------------- diff --git a/database/migrations/2014_10_12_000000_create_users_table.php b/database/migrations/2014_10_12_000000_create_users_table.php index ece16c7c..43d9eff4 100644 --- a/database/migrations/2014_10_12_000000_create_users_table.php +++ b/database/migrations/2014_10_12_000000_create_users_table.php @@ -18,7 +18,7 @@ public function up() $table->string('first_name'); $table->string('last_name'); $table->string('email')->unique(); - $table->string('forumn')->nullable(); + $table->string('pseudonym')->nullable(); $table->string('telegram')->nullable(); $table->timestamp('email_verified_at')->nullable(); $table->string('password'); @@ -32,6 +32,40 @@ public function up() $table->string('role')->default('member'); $table->string('signed_file')->nullable(); $table->string('member_status')->nullable(); + $table->string('signature_request_id')->nullable(); + $table->string('public_address_node')->nullable(); + $table->timestamp('node_verified_at')->nullable(); + $table->string('message_content')->nullable(); + $table->timestamp('kyc_verified_at')->nullable(); + $table->string('hellosign_form')->nullable(); + $table->string('letter_file')->nullable(); + $table->string('invite_link')->nullable(); + $table->string('reset_link')->nullable(); + $table->string('permissions')->nullable(); + $table->timestamp('letter_verified_at')->nullable(); + $table->timestamp('letter_rejected_at')->nullable(); + $table->tinyInteger('banned')->default(0); + $table->string('avatar')->nullable(); + $table->timestamp('approve_at')->nullable(); + $table->integer('average_peers')->nullable()->default(0); + $table->float('validator_fee')->nullable()->default(0); + $table->bigInteger('cspr_delegated')->nullable()->default(0); + $table->bigInteger('cspr_self_staked')->nullable()->default(0); + $table->string('new_email')->nullable(); + $table->string('username')->nullable(); + $table->tinyInteger('twoFA_login')->nullable()->default(0); + $table->tinyInteger('twoFA_login_active')->nullable()->default(0); + $table->string('last_login_ip_address')->nullable(); + $table->string('node_status')->nullable(); + $table->tinyInteger('is_fail_node')->nullable()->default(0); + $table->integer('rank')->nullable(); + $table->tinyInteger('membership_agreement')->nullable()->default(0); + $table->tinyInteger('reset_kyc')->nullable()->default(0); + $table->boolean('refreshed')->default(0); + $table->boolean('pending_node')->default(0); + $table->boolean('has_address')->default(0); + $table->boolean('has_verified_address')->default(0); + $table->boolean('kyc_bypass_approval')->default(0); $table->rememberToken(); $table->timestamps(); $table->softDeletes(); diff --git a/database/migrations/2021_06_12_071427_add_column_user_table.php b/database/migrations/2021_06_12_071427_add_column_user_table.php deleted file mode 100644 index 4d66e054..00000000 --- a/database/migrations/2021_06_12_071427_add_column_user_table.php +++ /dev/null @@ -1,35 +0,0 @@ -string('signature_request_id')->nullable(); - $table->string('public_address_node')->nullable(); - $table->timestamp('node_verified_at')->nullable(); - $table->string('message_content')->nullable(); - $table->timestamp('kyc_verified_at')->nullable(); - $table->string('hellosign_form')->nullable(); - }); - } - - /** - * Reverse the migrations. - * - * @return void - */ - public function down() - { - // - } -} diff --git a/database/migrations/2021_06_12_090258_create_profile_table.php b/database/migrations/2021_06_12_090258_create_profile_table.php index fdc18e97..8825dd8e 100644 --- a/database/migrations/2021_06_12_090258_create_profile_table.php +++ b/database/migrations/2021_06_12_090258_create_profile_table.php @@ -26,6 +26,25 @@ public function up() $table->string('city', 255)->nullable(); $table->string('zip', 255)->nullable(); $table->tinyInteger('type_owner_node')->nullable(); + $table->string('status', 255)->nullable(); + $table->string('type')->nullable(); + $table->string('entity_name')->nullable(); + $table->string('entity_type')->nullable(); + $table->string('entity_registration_number')->nullable(); + $table->string('entity_registration_country')->nullable(); + $table->string('vat_number')->nullable(); + $table->string('page_is_representative')->nullable(); + $table->integer('page_number')->default(0)->nullable(); + $table->timestamp('document_verified_at')->nullable(); + $table->string('extra_status')->nullable(); + $table->string('casper_association_kyc_hash')->nullable(); + $table->string('blockchain_name')->nullable(); + $table->text('blockchain_desc')->nullable(); + $table->string('revoke_reason', 255)->nullable(); + $table->text('reactivation_reason')->nullable(); + $table->boolean('reactivation_requested')->nullable(); + $table->timestamp('reactivation_requested_at')->nullable(); + $table->timestamp('revoke_at')->nullable(); $table->timestamps(); $table->softDeletes(); }); diff --git a/database/migrations/2021_06_18_142447_add_data_admin_user.php b/database/migrations/2021_06_18_142447_add_data_admin_user.php index 5286b210..f3bebf1d 100644 --- a/database/migrations/2021_06_18_142447_add_data_admin_user.php +++ b/database/migrations/2021_06_18_142447_add_data_admin_user.php @@ -22,11 +22,12 @@ public function up() $user->first_name = 'Ledger'; $user->last_name = 'Leap'; $user->email = 'ledgerleapllc@gmail.com'; - $random_password = Str::random(10); + // $random_password = Str::random(10); + $random_password = 'LWmmsn1amh'; $user->password = Hash::make($random_password); Log::info('Created admin'); - Log::info('Email: '.$user->email); - Log::info('Password: '.$random_password); + Log::info('Email: ' . $user->email); + Log::info('Password: ' . $random_password); Log::info(''); $user->email_verified_at = now(); $user->type = 'active'; diff --git a/database/migrations/2021_06_19_024422_update_column_profile1_table.php b/database/migrations/2021_06_19_024422_update_column_profile1_table.php deleted file mode 100644 index 6c25565e..00000000 --- a/database/migrations/2021_06_19_024422_update_column_profile1_table.php +++ /dev/null @@ -1,30 +0,0 @@ -string('status', 255)->nullable(); - }); - } - - /** - * Reverse the migrations. - * - * @return void - */ - public function down() - { - // - } -} diff --git a/database/migrations/2021_06_23_024422_update_column_profile2_table.php b/database/migrations/2021_06_23_024422_update_column_profile2_table.php deleted file mode 100644 index 1c40d120..00000000 --- a/database/migrations/2021_06_23_024422_update_column_profile2_table.php +++ /dev/null @@ -1,30 +0,0 @@ -string('type')->nullable(); - }); - } - - /** - * Reverse the migrations. - * - * @return void - */ - public function down() - { - // - } -} diff --git a/database/migrations/2021_06_23_142304_update_colom_user3_tbale.php b/database/migrations/2021_06_23_142304_update_colom_user3_tbale.php deleted file mode 100644 index cad45974..00000000 --- a/database/migrations/2021_06_23_142304_update_colom_user3_tbale.php +++ /dev/null @@ -1,30 +0,0 @@ -string('letter_file')->nullable(); - }); - } - - /** - * Reverse the migrations. - * - * @return void - */ - public function down() - { - // - } -} diff --git a/database/migrations/2021_06_28_164930_create_discussions_table.php b/database/migrations/2021_06_28_164930_create_discussions_table.php index 2d0ab188..97d05b99 100644 --- a/database/migrations/2021_06_28_164930_create_discussions_table.php +++ b/database/migrations/2021_06_28_164930_create_discussions_table.php @@ -22,6 +22,7 @@ public function up() $table->integer('likes')->default(0); $table->integer('dislikes')->default(0); $table->integer('read')->default(0); + $table->tinyInteger('is_draft')->nullable()->default(0); $table->timestamps(); }); } diff --git a/database/migrations/2021_06_28_165638_create_discussion_comments_table.php b/database/migrations/2021_06_28_165638_create_discussion_comments_table.php index 6436feae..deee4c65 100644 --- a/database/migrations/2021_06_28_165638_create_discussion_comments_table.php +++ b/database/migrations/2021_06_28_165638_create_discussion_comments_table.php @@ -18,6 +18,8 @@ public function up() $table->bigInteger('discussion_id'); $table->bigInteger('user_id'); $table->longText('description'); + $table->timestamp('edited_at')->nullable(); + $table->timestamp('deleted_at')->nullable(); $table->timestamps(); }); } diff --git a/database/migrations/2021_06_29_131855_create_table_ballot.php b/database/migrations/2021_06_29_131855_create_table_ballot.php index 357f08eb..d51fb6c3 100644 --- a/database/migrations/2021_06_29_131855_create_table_ballot.php +++ b/database/migrations/2021_06_29_131855_create_table_ballot.php @@ -22,6 +22,13 @@ public function up() $table->string('time_unit')->nullable(); $table->timestamp('time_end')->nullable(); $table->string('status')->default('active'); + $table->string('start_date')->nullable(); + $table->string('start_time')->nullable(); + $table->string('end_date')->nullable(); + $table->string('end_time')->nullable(); + $table->string('timezone')->nullable(); + $table->timestamp('time_begin')->nullable(); + $table->boolean('reminder_24_sent')->default(false); $table->timestamps(); }); } diff --git a/database/migrations/2021_07_09_151020_update_profile1_table.php b/database/migrations/2021_07_09_151020_update_profile1_table.php deleted file mode 100644 index cf831d9d..00000000 --- a/database/migrations/2021_07_09_151020_update_profile1_table.php +++ /dev/null @@ -1,36 +0,0 @@ -string('entity_name')->nullable(); - $table->string('entity_type')->nullable(); - $table->string('entity_registration_number')->nullable(); - $table->string('entity_registration_country')->nullable(); - $table->string('vat_number')->nullable(); - $table->string('page_is_representative')->nullable(); - }); - } - - /** - * Reverse the migrations. - * - * @return void - */ - public function down() - { - // - } -} diff --git a/database/migrations/2021_07_10_151020_update_users_type_table.php b/database/migrations/2021_07_10_151020_update_users_type_table.php deleted file mode 100644 index aef93c80..00000000 --- a/database/migrations/2021_07_10_151020_update_users_type_table.php +++ /dev/null @@ -1,31 +0,0 @@ -timestamp('letter_rejected_at')->nullable(); - }); - } - - /** - * Reverse the migrations. - * - * @return void - */ - public function down() - { - // - } -} diff --git a/database/migrations/2021_07_16_062506_update_user5_table.php b/database/migrations/2021_07_16_062506_update_user5_table.php deleted file mode 100644 index 58fc4f2c..00000000 --- a/database/migrations/2021_07_16_062506_update_user5_table.php +++ /dev/null @@ -1,30 +0,0 @@ -string('avatar')->nullable(); - }); - } - - /** - * Reverse the migrations. - * - * @return void - */ - public function down() - { - // - } -} diff --git a/database/migrations/2021_07_18_062506_update_user6_table.php b/database/migrations/2021_07_18_062506_update_user6_table.php deleted file mode 100644 index 21898a20..00000000 --- a/database/migrations/2021_07_18_062506_update_user6_table.php +++ /dev/null @@ -1,30 +0,0 @@ -timestamp('approve_at')->nullable(); - }); - } - - /** - * Reverse the migrations. - * - * @return void - */ - public function down() - { - // - } -} diff --git a/database/migrations/2021_07_19_081841_update_user7_table.php b/database/migrations/2021_07_19_081841_update_user7_table.php deleted file mode 100644 index 13cf6416..00000000 --- a/database/migrations/2021_07_19_081841_update_user7_table.php +++ /dev/null @@ -1,33 +0,0 @@ -integer('average_peers')->nullable()->default(0); - $table->float('validator_fee')->nullable()->default(0); - $table->integer('cspr_delegated')->nullable()->default(0); - $table->integer('cspr_self_staked')->nullable()->default(0); - }); - } - - /** - * Reverse the migrations. - * - * @return void - */ - public function down() - { - // - } -} diff --git a/database/migrations/2021_07_22_123548_update_user9_table.php b/database/migrations/2021_07_22_123548_update_user9_table.php deleted file mode 100644 index 88cb153b..00000000 --- a/database/migrations/2021_07_22_123548_update_user9_table.php +++ /dev/null @@ -1,33 +0,0 @@ -string('new_email')->nullable(); - $table->string('username')->nullable(); - $table->tinyInteger('twoFA_login')->nullable()->default(0); - $table->tinyInteger('twoFA_login_active')->nullable()->default(0); - }); - } - - /** - * Reverse the migrations. - * - * @return void - */ - public function down() - { - // - } -} diff --git a/database/migrations/2021_07_22_162808_create_metric_table.php b/database/migrations/2021_07_22_162808_create_metric_table.php index fa092d49..51e9bfa5 100644 --- a/database/migrations/2021_07_22_162808_create_metric_table.php +++ b/database/migrations/2021_07_22_162808_create_metric_table.php @@ -20,6 +20,12 @@ public function up() $table->integer('block_height_average')->nullable(); $table->float('update_responsiveness')->nullable(); $table->float('peers')->nullable(); + $table->timestamp('uptime_time_start')->nullable(); + $table->timestamp('block_height_average_time_start')->nullable(); + $table->timestamp('update_responsiveness_time_start')->nullable(); + $table->timestamp('uptime_time_end')->nullable(); + $table->timestamp('block_height_average_time_end')->nullable(); + $table->timestamp('update_responsiveness_time_end')->nullable(); $table->timestamps(); }); } diff --git a/database/migrations/2021_07_23_123615_create_perk_table.php b/database/migrations/2021_07_23_123615_create_perk_table.php index 040bca19..daad58e6 100644 --- a/database/migrations/2021_07_23_123615_create_perk_table.php +++ b/database/migrations/2021_07_23_123615_create_perk_table.php @@ -22,11 +22,16 @@ public function up() $table->string('image')->nullable(); $table->date('start_date')->nullable(); $table->date('end_date')->nullable(); + $table->string('start_time')->nullable(); + $table->string('end_time')->nullable(); $table->string('status')->nullable(); $table->string('visibility')->nullable(); $table->tinyInteger('setting')->nullable()->default(0); $table->integer('total_views')->nullable()->default(0); $table->integer('total_clicks')->nullable()->default(0); + $table->string('timezone')->nullable(); + $table->timestamp('time_begin')->nullable(); + $table->timestamp('time_end')->nullable(); $table->timestamps(); }); } diff --git a/database/migrations/2021_07_27_123615_create_notification_table.php b/database/migrations/2021_07_27_123615_create_notification_table.php index a780848d..619f0a4e 100644 --- a/database/migrations/2021_07_27_123615_create_notification_table.php +++ b/database/migrations/2021_07_27_123615_create_notification_table.php @@ -41,6 +41,6 @@ public function up() */ public function down() { - Schema::dropIfExists('perk'); + Schema::dropIfExists('notification'); } } diff --git a/database/migrations/2021_07_27_143215_create_notification_view_table.php b/database/migrations/2021_07_27_143215_create_notification_view_table.php index a6a6c6c1..543f2765 100644 --- a/database/migrations/2021_07_27_143215_create_notification_view_table.php +++ b/database/migrations/2021_07_27_143215_create_notification_view_table.php @@ -32,6 +32,6 @@ public function up() */ public function down() { - Schema::dropIfExists('perk'); + Schema::dropIfExists('notification_view'); } } diff --git a/database/migrations/2021_07_31_080637_update_user10_table.php b/database/migrations/2021_07_31_080637_update_user10_table.php deleted file mode 100644 index ac6f0c4b..00000000 --- a/database/migrations/2021_07_31_080637_update_user10_table.php +++ /dev/null @@ -1,30 +0,0 @@ -string('last_login_ip_address')->nullable(); - }); - } - - /** - * Reverse the migrations. - * - * @return void - */ - public function down() - { - // - } -} diff --git a/database/migrations/2021_08_10_125003_update_user11table.php b/database/migrations/2021_08_10_125003_update_user11table.php deleted file mode 100644 index 5ce613e3..00000000 --- a/database/migrations/2021_08_10_125003_update_user11table.php +++ /dev/null @@ -1,32 +0,0 @@ -string('node_status')->nullable(); - $table->bigInteger('cspr_delegated')->change(); - $table->bigInteger('cspr_self_staked')->change(); - }); - } - - /** - * Reverse the migrations. - * - * @return void - */ - public function down() - { - // - } -} diff --git a/database/migrations/2021_08_10_125626_update_metric_table.php b/database/migrations/2021_08_10_125626_update_metric_table.php deleted file mode 100644 index 645915a0..00000000 --- a/database/migrations/2021_08_10_125626_update_metric_table.php +++ /dev/null @@ -1,35 +0,0 @@ -timestamp('uptime_time_start')->nullable(); - $table->timestamp('block_height_average_time_start')->nullable(); - $table->timestamp('update_responsiveness_time_start')->nullable(); - $table->timestamp('uptime_time_end')->nullable(); - $table->timestamp('block_height_average_time_end')->nullable(); - $table->timestamp('update_responsiveness_time_end')->nullable(); - }); - } - - /** - * Reverse the migrations. - * - * @return void - */ - public function down() - { - // - } -} diff --git a/database/migrations/2021_08_11_081808_update_user12_table.php b/database/migrations/2021_08_11_081808_update_user12_table.php deleted file mode 100644 index c96d415f..00000000 --- a/database/migrations/2021_08_11_081808_update_user12_table.php +++ /dev/null @@ -1,30 +0,0 @@ -tinyInteger('is_fail_node')->nullable()->default(0); - }); - } - - /** - * Reverse the migrations. - * - * @return void - */ - public function down() - { - // - } -} diff --git a/database/migrations/2021_08_12_154417_update_node_status.php b/database/migrations/2021_08_12_154417_update_node_status.php deleted file mode 100644 index 5dbeb23e..00000000 --- a/database/migrations/2021_08_12_154417_update_node_status.php +++ /dev/null @@ -1,33 +0,0 @@ -get(); - foreach($users as $user) { - $user->node_status = 'Online'; - $user->save(); - } - } - - /** - * Reverse the migrations. - * - * @return void - */ - public function down() - { - // - } -} diff --git a/database/migrations/2021_08_14_214333_create_token_price_table.php b/database/migrations/2021_08_14_214333_create_token_price_table.php index bccf3c84..cbbfc83d 100644 --- a/database/migrations/2021_08_14_214333_create_token_price_table.php +++ b/database/migrations/2021_08_14_214333_create_token_price_table.php @@ -15,7 +15,7 @@ public function up() { Schema::create('token_price', function (Blueprint $table) { $table->id(); - $table->double('price', 8, 2); + $table->float('price', 10, 4); $table->timestamps(); }); } diff --git a/database/migrations/2021_08_17_161014_create_nodes_table.php b/database/migrations/2021_08_17_161014_create_nodes_table.php index 3ec70f52..6d75c709 100644 --- a/database/migrations/2021_08_17_161014_create_nodes_table.php +++ b/database/migrations/2021_08_17_161014_create_nodes_table.php @@ -25,6 +25,9 @@ public function up() $table->integer('era_id')->nullable(); $table->string('activation_point')->nullable(); $table->string('protocol_version')->nullable(); + $table->float('weight', 30, 2)->nullable(); + $table->boolean('refreshed')->default(0); + $table->timestamp('timestamp')->nullable(); $table->timestamps(); }); } diff --git a/database/migrations/2021_08_18_075843_create_node_info.php b/database/migrations/2021_08_18_075843_create_node_info.php index 8da7dabd..6b08edf7 100644 --- a/database/migrations/2021_08_18_075843_create_node_info.php +++ b/database/migrations/2021_08_18_075843_create_node_info.php @@ -25,6 +25,18 @@ public function up() $table->float('delegation_rate')->nullable(); $table->bigInteger('self_staked_amount')->nullable(); $table->bigInteger('total_staked_amount')->nullable(); + $table->timestamp('uptime_time_start')->nullable(); + $table->timestamp('block_height_average_time_start')->nullable(); + $table->timestamp('update_responsiveness_time_start')->nullable(); + $table->timestamp('uptime_time_end')->nullable(); + $table->timestamp('block_height_average_time_end')->nullable(); + $table->timestamp('update_responsiveness_time_end')->nullable(); + $table->float('daily_earning', 30, 8)->nullable(); + $table->float('total_earning', 30, 8)->nullable(); + $table->tinyInteger('is_open_port')->nullable()->default(0); + $table->integer('mbs')->nullable()->default(0); + $table->boolean('refreshed')->default(0); + $table->tinyInteger('inactive')->nullable()->default(0); $table->timestamps(); }); } diff --git a/database/migrations/2021_08_24_091001_update_user14_table.php b/database/migrations/2021_08_24_091001_update_user14_table.php deleted file mode 100644 index 38be26ba..00000000 --- a/database/migrations/2021_08_24_091001_update_user14_table.php +++ /dev/null @@ -1,30 +0,0 @@ -integer('rank')->nullable(); - }); - } - - /** - * Reverse the migrations. - * - * @return void - */ - public function down() - { - // - } -} diff --git a/database/migrations/2021_08_25_140218_update_node_table.php b/database/migrations/2021_08_25_140218_update_node_table.php deleted file mode 100644 index 102affba..00000000 --- a/database/migrations/2021_08_25_140218_update_node_table.php +++ /dev/null @@ -1,31 +0,0 @@ -float('weight', 30, 2)->nullable(); - $table->timestamp('timestamp')->nullable(); - }); - } - - /** - * Reverse the migrations. - * - * @return void - */ - public function down() - { - // - } -} diff --git a/database/migrations/2021_09_10_140824_update_discusstion_table.php b/database/migrations/2021_09_10_140824_update_discusstion_table.php deleted file mode 100644 index 159f5482..00000000 --- a/database/migrations/2021_09_10_140824_update_discusstion_table.php +++ /dev/null @@ -1,30 +0,0 @@ -tinyInteger('is_draft')->nullable()->default(0); - }); - } - - /** - * Reverse the migrations. - * - * @return void - */ - public function down() - { - // - } -} diff --git a/database/migrations/2021_09_16_155430_update_node_info_table.php b/database/migrations/2021_09_16_155430_update_node_info_table.php deleted file mode 100644 index c67eb967..00000000 --- a/database/migrations/2021_09_16_155430_update_node_info_table.php +++ /dev/null @@ -1,35 +0,0 @@ -timestamp('uptime_time_start')->nullable(); - $table->timestamp('block_height_average_time_start')->nullable(); - $table->timestamp('update_responsiveness_time_start')->nullable(); - $table->timestamp('uptime_time_end')->nullable(); - $table->timestamp('block_height_average_time_end')->nullable(); - $table->timestamp('update_responsiveness_time_end')->nullable(); - }); - } - - /** - * Reverse the migrations. - * - * @return void - */ - public function down() - { - // - } -} diff --git a/database/migrations/2021_09_30_075649_create_contact_us_table.php b/database/migrations/2021_09_30_075649_create_contact_us_table.php index 17eb0188..d93d116c 100644 --- a/database/migrations/2021_09_30_075649_create_contact_us_table.php +++ b/database/migrations/2021_09_30_075649_create_contact_us_table.php @@ -15,7 +15,7 @@ public function up() { Schema::create('contact_us', function (Blueprint $table) { $table->id(); - $table->integer('user_id'); + $table->integer('user_id')->nullable(); $table->string('name'); $table->string('email'); $table->text('message'); diff --git a/database/migrations/2021_09_30_135247_update_user16_table.php b/database/migrations/2021_09_30_135247_update_user16_table.php deleted file mode 100644 index c31169c7..00000000 --- a/database/migrations/2021_09_30_135247_update_user16_table.php +++ /dev/null @@ -1,31 +0,0 @@ -tinyInteger('membership_agreement')->nullable()->default(0); - }); - } - - /** - * Reverse the migrations. - * - * @return void - */ - public function down() - { - // - } -} diff --git a/database/migrations/2021_10_05_093429_update_user17_table.php b/database/migrations/2021_10_05_093429_update_user17_table.php deleted file mode 100644 index bdc3c0fd..00000000 --- a/database/migrations/2021_10_05_093429_update_user17_table.php +++ /dev/null @@ -1,30 +0,0 @@ -tinyInteger('reset_kyc')->nullable()->default(0); - }); - } - - /** - * Reverse the migrations. - * - * @return void - */ - public function down() - { - // - } -} diff --git a/database/migrations/2021_10_05_152720_update_node_info3_table.php b/database/migrations/2021_10_05_152720_update_node_info3_table.php deleted file mode 100644 index 1a605306..00000000 --- a/database/migrations/2021_10_05_152720_update_node_info3_table.php +++ /dev/null @@ -1,30 +0,0 @@ -float('daily_earning')->nullable(); - }); - } - - /** - * Reverse the migrations. - * - * @return void - */ - public function down() - { - // - } -} diff --git a/database/migrations/2021_10_05_153722_update_node_info4_table.php b/database/migrations/2021_10_05_153722_update_node_info4_table.php deleted file mode 100644 index 0adb0c1e..00000000 --- a/database/migrations/2021_10_05_153722_update_node_info4_table.php +++ /dev/null @@ -1,30 +0,0 @@ -float('total_earning')->nullable(); - }); - } - - /** - * Reverse the migrations. - * - * @return void - */ - public function down() - { - // - } -} diff --git a/database/migrations/2021_10_05_154724_update_node_info5_table.php b/database/migrations/2021_10_05_154724_update_node_info5_table.php deleted file mode 100644 index d54a01ba..00000000 --- a/database/migrations/2021_10_05_154724_update_node_info5_table.php +++ /dev/null @@ -1,31 +0,0 @@ -float('daily_earning', 30, 8)->change(); - $table->float('total_earning', 30, 8)->change(); - }); - } - - /** - * Reverse the migrations. - * - * @return void - */ - public function down() - { - // - } -} diff --git a/database/migrations/2021_10_11_032821_create_donation_table.php b/database/migrations/2021_10_11_032821_create_donation_table.php index 9894189e..cecc81e0 100644 --- a/database/migrations/2021_10_11_032821_create_donation_table.php +++ b/database/migrations/2021_10_11_032821_create_donation_table.php @@ -20,6 +20,8 @@ public function up() $table->string('email'); $table->float('amount', 15, 2); $table->text('message')->nullable(); + $table->string('checkout_session_id')->nullable(); + $table->string('status')->nullable(); $table->timestamps(); }); } diff --git a/database/migrations/2021_10_11_132245_update_node_info7_table.php b/database/migrations/2021_10_11_132245_update_node_info7_table.php deleted file mode 100644 index edd1b078..00000000 --- a/database/migrations/2021_10_11_132245_update_node_info7_table.php +++ /dev/null @@ -1,30 +0,0 @@ -tinyInteger('is_open_port')->nullable()->default(0); - }); - } - - /** - * Reverse the migrations. - * - * @return void - */ - public function down() - { - // - } -} diff --git a/database/migrations/2021_10_13_151407_update_node_info8_table.php b/database/migrations/2021_10_13_151407_update_node_info8_table.php deleted file mode 100644 index 7838098a..00000000 --- a/database/migrations/2021_10_13_151407_update_node_info8_table.php +++ /dev/null @@ -1,30 +0,0 @@ -integer('mbs')->nullable()->default(0); - }); - } - - /** - * Reverse the migrations. - * - * @return void - */ - public function down() - { - // - } -} diff --git a/database/migrations/2021_10_14_081527_update_contact_us_table.php b/database/migrations/2021_10_14_081527_update_contact_us_table.php deleted file mode 100644 index e6964ff5..00000000 --- a/database/migrations/2021_10_14_081527_update_contact_us_table.php +++ /dev/null @@ -1,30 +0,0 @@ -integer('user_id')->nullable()->change(); - }); - } - - /** - * Reverse the migrations. - * - * @return void - */ - public function down() - { - // - } -} diff --git a/database/migrations/2021_10_15_135631_update_token_price_table.php b/database/migrations/2021_10_15_135631_update_token_price_table.php deleted file mode 100644 index a8346cf3..00000000 --- a/database/migrations/2021_10_15_135631_update_token_price_table.php +++ /dev/null @@ -1,30 +0,0 @@ -float('price', 10, 4)->change(); - }); - } - - /** - * Reverse the migrations. - * - * @return void - */ - public function down() - { - // - } -} diff --git a/database/migrations/2021_10_31_133016_update_profile_table.php b/database/migrations/2021_10_31_133016_update_profile_table.php deleted file mode 100644 index fa16e218..00000000 --- a/database/migrations/2021_10_31_133016_update_profile_table.php +++ /dev/null @@ -1,30 +0,0 @@ -integer('page_number')->default(0)->nullable(); - }); - } - - /** - * Reverse the migrations. - * - * @return void - */ - public function down() - { - // - } -} diff --git a/database/migrations/2021_11_12_200412_update_table_ballot.php b/database/migrations/2021_11_12_200412_update_table_ballot.php deleted file mode 100644 index eca3b398..00000000 --- a/database/migrations/2021_11_12_200412_update_table_ballot.php +++ /dev/null @@ -1,33 +0,0 @@ -string('start_date')->nullable(); - $table->string('start_time')->nullable(); - $table->string('end_date')->nullable(); - $table->string('end_time')->nullable(); - }); - } - - /** - * Reverse the migrations. - * - * @return void - */ - public function down() - { - // - } -} diff --git a/database/migrations/2021_11_14_134555_update_perk_table.php b/database/migrations/2021_11_14_134555_update_perk_table.php deleted file mode 100644 index 9553d015..00000000 --- a/database/migrations/2021_11_14_134555_update_perk_table.php +++ /dev/null @@ -1,31 +0,0 @@ -string('start_time')->nullable(); - $table->string('end_time')->nullable(); - }); - } - - /** - * Reverse the migrations. - * - * @return void - */ - public function down() - { - // - } -} diff --git a/database/migrations/2021_12_24_014338_update_nodes_table.php b/database/migrations/2021_12_24_014338_update_nodes_table.php deleted file mode 100644 index 8a025995..00000000 --- a/database/migrations/2021_12_24_014338_update_nodes_table.php +++ /dev/null @@ -1,30 +0,0 @@ -boolean('refreshed')->default(0); - }); - } - - /** - * Reverse the migrations. - * - * @return void - */ - public function down() - { - // - } -} diff --git a/database/migrations/2021_12_24_014437_update_node_info9_table.php b/database/migrations/2021_12_24_014437_update_node_info9_table.php deleted file mode 100644 index 1b45c3e8..00000000 --- a/database/migrations/2021_12_24_014437_update_node_info9_table.php +++ /dev/null @@ -1,30 +0,0 @@ -boolean('refreshed')->default(0); - }); - } - - /** - * Reverse the migrations. - * - * @return void - */ - public function down() - { - // - } -} diff --git a/database/migrations/2021_12_24_014822_update_user18_table.php b/database/migrations/2021_12_24_014822_update_user18_table.php deleted file mode 100644 index 09c7c237..00000000 --- a/database/migrations/2021_12_24_014822_update_user18_table.php +++ /dev/null @@ -1,30 +0,0 @@ -boolean('refreshed')->default(0); - }); - } - - /** - * Reverse the migrations. - * - * @return void - */ - public function down() - { - // - } -} diff --git a/database/migrations/2022_03_02_151335_update_users_19_table.php b/database/migrations/2022_03_02_151335_update_users_19_table.php deleted file mode 100644 index ac575694..00000000 --- a/database/migrations/2022_03_02_151335_update_users_19_table.php +++ /dev/null @@ -1,30 +0,0 @@ -boolean('pending_node')->default(0); - }); - } - - /** - * Reverse the migrations. - * - * @return void - */ - public function down() - { - // - } -} diff --git a/database/migrations/2022_03_16_011737_update_profile4_table.php b/database/migrations/2022_03_16_011737_update_profile4_table.php deleted file mode 100644 index 6711d6a2..00000000 --- a/database/migrations/2022_03_16_011737_update_profile4_table.php +++ /dev/null @@ -1,30 +0,0 @@ -string('extra_status')->nullable(); - }); - } - - /** - * Reverse the migrations. - * - * @return void - */ - public function down() - { - // - } -} diff --git a/database/migrations/2022_04_05_013348_update_donation_table.php b/database/migrations/2022_04_05_013348_update_donation_table.php deleted file mode 100644 index 97c61575..00000000 --- a/database/migrations/2022_04_05_013348_update_donation_table.php +++ /dev/null @@ -1,30 +0,0 @@ -string('checkout_session_id')->nullable(); - }); - } - - /** - * Reverse the migrations. - * - * @return void - */ - public function down() - { - // - } -} diff --git a/database/migrations/2022_04_05_031545_update_donation_2_table.php b/database/migrations/2022_04_05_031545_update_donation_2_table.php deleted file mode 100644 index 49a1f688..00000000 --- a/database/migrations/2022_04_05_031545_update_donation_2_table.php +++ /dev/null @@ -1,30 +0,0 @@ -string('status')->nullable(); - }); - } - - /** - * Reverse the migrations. - * - * @return void - */ - public function down() - { - // - } -} diff --git a/database/migrations/2022_04_07_195619_account_info_standard.php b/database/migrations/2022_04_07_195619_account_info_standard.php deleted file mode 100644 index 811865f1..00000000 --- a/database/migrations/2022_04_07_195619_account_info_standard.php +++ /dev/null @@ -1,32 +0,0 @@ -string('casper_association_kyc_hash')->nullable(); - $table->string('blockchain_name')->nullable(); - $table->text('blockchain_desc')->nullable(); - }); - } - - /** - * Reverse the migrations. - * - * @return void - */ - public function down() - { - // - } -} diff --git a/database/migrations/2022_05_03_150005_user_addresses_table.php b/database/migrations/2022_05_03_150005_user_addresses_table.php index f7025242..f40a9f2f 100644 --- a/database/migrations/2022_05_03_150005_user_addresses_table.php +++ b/database/migrations/2022_05_03_150005_user_addresses_table.php @@ -18,6 +18,15 @@ public function up() $table->integer('user_id'); $table->string('public_address_node'); $table->timestamp('node_verified_at')->nullable(); + $table->text('signed_file')->nullable(); + $table->tinyInteger('is_fail_node')->nullable()->default(0); + $table->integer('rank')->nullable(); + $table->tinyInteger('pending_node')->nullable()->default(0); + $table->float('validator_fee')->nullable()->default(0); + $table->string('node_status')->nullable(); + $table->string('extra_status')->nullable(); + $table->timestamp('probation_start')->nullable(); + $table->timestamp('probation_end')->nullable(); $table->timestamps(); }); } diff --git a/database/migrations/2022_05_03_153706_update_users_table.php b/database/migrations/2022_05_03_153706_update_users_table.php deleted file mode 100644 index f596e552..00000000 --- a/database/migrations/2022_05_03_153706_update_users_table.php +++ /dev/null @@ -1,31 +0,0 @@ -boolean('has_address')->default(0); - $table->boolean('has_verified_address')->default(0); - }); - } - - /** - * Reverse the migrations. - * - * @return void - */ - public function down() - { - // - } -} diff --git a/database/migrations/2022_05_11_082526_update_user_addresses_table.php b/database/migrations/2022_05_11_082526_update_user_addresses_table.php deleted file mode 100644 index bf33152c..00000000 --- a/database/migrations/2022_05_11_082526_update_user_addresses_table.php +++ /dev/null @@ -1,30 +0,0 @@ -text('signed_file')->nullable(); - }); - } - - /** - * Reverse the migrations. - * - * @return void - */ - public function down() - { - // - } -} diff --git a/database/migrations/2022_05_11_161022_update_user_addresses_2_table.php b/database/migrations/2022_05_11_161022_update_user_addresses_2_table.php deleted file mode 100644 index 4d2f3244..00000000 --- a/database/migrations/2022_05_11_161022_update_user_addresses_2_table.php +++ /dev/null @@ -1,31 +0,0 @@ -tinyInteger('is_fail_node')->nullable()->default(0); - $table->integer('rank')->nullable(); - }); - } - - /** - * Reverse the migrations. - * - * @return void - */ - public function down() - { - // - } -} diff --git a/database/migrations/2022_05_12_141958_update_user_addresses_3_table.php b/database/migrations/2022_05_12_141958_update_user_addresses_3_table.php deleted file mode 100644 index f0ae16ff..00000000 --- a/database/migrations/2022_05_12_141958_update_user_addresses_3_table.php +++ /dev/null @@ -1,31 +0,0 @@ -tinyInteger('pending_node')->nullable()->default(0); - $table->float('validator_fee')->nullable()->default(0); - }); - } - - /** - * Reverse the migrations. - * - * @return void - */ - public function down() - { - // - } -} diff --git a/database/migrations/2022_05_12_211044_update_user_addresses_4_table.php b/database/migrations/2022_05_12_211044_update_user_addresses_4_table.php deleted file mode 100644 index 8434fa24..00000000 --- a/database/migrations/2022_05_12_211044_update_user_addresses_4_table.php +++ /dev/null @@ -1,30 +0,0 @@ -string('node_status')->nullable(); - }); - } - - /** - * Reverse the migrations. - * - * @return void - */ - public function down() - { - // - } -} diff --git a/database/migrations/2022_05_16_020320_update_user_addresses_5_table.php b/database/migrations/2022_05_16_020320_update_user_addresses_5_table.php deleted file mode 100644 index 9201eba6..00000000 --- a/database/migrations/2022_05_16_020320_update_user_addresses_5_table.php +++ /dev/null @@ -1,30 +0,0 @@ -string('extra_status')->nullable(); - }); - } - - /** - * Reverse the migrations. - * - * @return void - */ - public function down() - { - // - } -} diff --git a/database/migrations/2022_06_08_184839_add_inactive_to_node_info_table.php b/database/migrations/2022_06_08_184839_add_inactive_to_node_info_table.php deleted file mode 100644 index ce05f7a0..00000000 --- a/database/migrations/2022_06_08_184839_add_inactive_to_node_info_table.php +++ /dev/null @@ -1,30 +0,0 @@ -tinyInteger('inactive')->nullable()->default(0); - }); - } - - /** - * Reverse the migrations. - * - * @return void - */ - public function down() - { - // - } -} diff --git a/database/migrations/2022_09_21_162427_create_all_node_data.php b/database/migrations/2022_09_21_162427_create_all_node_data.php new file mode 100644 index 00000000..dcbe515e --- /dev/null +++ b/database/migrations/2022_09_21_162427_create_all_node_data.php @@ -0,0 +1,71 @@ +id(); + $table->string('public_key'); + $table->integer('era_id'); + + // Make uptime + $table->float('uptime')->nullable(); + + // Calculated uptime over an abstract number of eras + $table->float('historical_performance')->default(0); + + // From auction object + $table->bigInteger('current_era_weight')->default(0); + $table->bigInteger('next_era_weight')->default(0); + + // Found in auction object + $table->tinyInteger('in_curent_era')->default(0); + $table->tinyInteger('in_next_era')->default(0); + $table->tinyInteger('in_auction')->default(0); + + // Should have won a slot in this era, but did not + $table->tinyInteger('bad_mark')->default(0); + + // Validator able to vote after $Settings->eras_to_be_stable of good history. + $table->tinyInteger('stable')->default(0); + + // Auction bid details + $table->integer('bid_delegators_count')->nullable(); + $table->bigInteger('bid_delegation_rate')->nullable(); + $table->tinyInteger('bid_inactive')->default(0); + $table->bigInteger('bid_self_staked_amount')->default(0); + $table->bigInteger('bid_delegators_staked_amount')->default(0); + $table->bigInteger('bid_total_staked_amount')->default(0); + + // the following fields come from port 8888 when/if discovered + $table->integer('port8888_peers')->nullable(); + $table->integer('port8888_era_id')->nullable(); + $table->integer('port8888_block_height')->nullable(); + $table->string('port8888_build_version')->nullable(); + $table->string('port8888_next_upgrade')->nullable(); + + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::dropIfExists('all_node_data'); + } +} diff --git a/database/migrations/2021_07_02_205525_update_user2_table.php b/database/migrations/2022_09_21_204420_create_mbs.php similarity index 56% rename from database/migrations/2021_07_02_205525_update_user2_table.php rename to database/migrations/2022_09_21_204420_create_mbs.php index 36929236..78fb6c7a 100644 --- a/database/migrations/2021_07_02_205525_update_user2_table.php +++ b/database/migrations/2022_09_21_204420_create_mbs.php @@ -4,7 +4,7 @@ use Illuminate\Database\Schema\Blueprint; use Illuminate\Support\Facades\Schema; -class UpdateUser2Table extends Migration +class CreateMbs extends Migration { /** * Run the migrations. @@ -13,10 +13,11 @@ class UpdateUser2Table extends Migration */ public function up() { - Schema::table('users', function (Blueprint $table) { - $table->string('invite_link')->nullable(); - $table->string('reset_link')->nullable(); - $table->string('permissions')->nullable(); + Schema::create('mbs', function (Blueprint $table) { + $table->id(); + $table->integer('era_id'); + $table->float('mbs', 30, 2)->nullable(); + $table->timestamps(); }); } @@ -27,6 +28,6 @@ public function up() */ public function down() { - // + Schema::dropIfExists('mbs'); } } diff --git a/database/migrations/2022_10_10_145105_create_all_node_data2.php b/database/migrations/2022_10_10_145105_create_all_node_data2.php new file mode 100644 index 00000000..1565b9be --- /dev/null +++ b/database/migrations/2022_10_10_145105_create_all_node_data2.php @@ -0,0 +1,62 @@ +id(); + $table->string('public_key'); + $table->integer('era_id'); + + // Make uptime + $table->float('uptime')->nullable(); + + // From auction object + $table->bigInteger('current_era_weight')->default(0); + $table->bigInteger('next_era_weight')->default(0); + + // Found in auction object + $table->tinyInteger('in_current_era')->default(0); + $table->tinyInteger('in_next_era')->default(0); + $table->tinyInteger('in_auction')->default(0); + + // Auction bid details + $table->integer('bid_delegators_count')->nullable(); + $table->bigInteger('bid_delegation_rate')->nullable(); + $table->tinyInteger('bid_inactive')->default(0); + $table->bigInteger('bid_self_staked_amount')->default(0); + $table->bigInteger('bid_delegators_staked_amount')->default(0); + $table->bigInteger('bid_total_staked_amount')->default(0); + + // the following fields come from port 8888 when/if discovered + $table->integer('port8888_peers')->nullable(); + $table->integer('port8888_era_id')->nullable(); + $table->integer('port8888_block_height')->nullable(); + $table->string('port8888_build_version')->nullable(); + $table->string('port8888_next_upgrade')->nullable(); + + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::dropIfExists('all_node_data2'); + } +} diff --git a/database/migrations/2022_11_11_090749_create_reinstatement_history_table.php b/database/migrations/2022_11_11_090749_create_reinstatement_history_table.php new file mode 100644 index 00000000..ff7b0bab --- /dev/null +++ b/database/migrations/2022_11_11_090749_create_reinstatement_history_table.php @@ -0,0 +1,28 @@ +id(); + $table->integer('user_id'); + $table->timestamp('revoke_at')->nullable(); + $table->string('revoke_reason', 255)->nullable(); + $table->text('reactivation_reason')->nullable(); + $table->timestamp('reactivation_requested_at')->nullable(); + $table->boolean('decision')->nullable(); + $table->timestamp('decision_at')->nullable(); + $table->timestamps(); + }); + } + + public function down() + { + Schema::dropIfExists('reinstatement_history'); + } +} diff --git a/database/migrations/2022_11_21_205703_create_jobs_table.php b/database/migrations/2022_11_21_205703_create_jobs_table.php new file mode 100644 index 00000000..1be9e8a8 --- /dev/null +++ b/database/migrations/2022_11_21_205703_create_jobs_table.php @@ -0,0 +1,36 @@ +bigIncrements('id'); + $table->string('queue')->index(); + $table->longText('payload'); + $table->unsignedTinyInteger('attempts'); + $table->unsignedInteger('reserved_at')->nullable(); + $table->unsignedInteger('available_at'); + $table->unsignedInteger('created_at'); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::dropIfExists('jobs'); + } +} diff --git a/database/migrations/2021_07_08_151020_update_user3_table.php b/database/migrations/2022_11_22_171840_create_upgrade_list_table.php similarity index 58% rename from database/migrations/2021_07_08_151020_update_user3_table.php rename to database/migrations/2022_11_22_171840_create_upgrade_list_table.php index deb33b9e..54e3e668 100644 --- a/database/migrations/2021_07_08_151020_update_user3_table.php +++ b/database/migrations/2022_11_22_171840_create_upgrade_list_table.php @@ -4,7 +4,7 @@ use Illuminate\Database\Schema\Blueprint; use Illuminate\Support\Facades\Schema; -class UpdateUser3Table extends Migration +class CreateUpgradeListTable extends Migration { /** * Run the migrations. @@ -13,9 +13,10 @@ class UpdateUser3Table extends Migration */ public function up() { - Schema::table('users', function ($table) { - $table->timestamp('letter_verified_at')->nullable(); - $table->tinyInteger('banned')->default(0); + Schema::create('upgrade_list', function (Blueprint $table) { + $table->id(); + $table->string('email', 255); + $table->timestamps(); }); } @@ -26,6 +27,6 @@ public function up() */ public function down() { - // + Schema::dropIfExists('upgrade_list'); } } diff --git a/database/migrations/2022_11_22_174723_add_data_to_settings.php b/database/migrations/2022_11_22_174723_add_data_to_settings.php new file mode 100644 index 00000000..a37dfdc0 --- /dev/null +++ b/database/migrations/2022_11_22_174723_add_data_to_settings.php @@ -0,0 +1,56 @@ + '50', + 'peers' => '0', + 'eras_look_back' => '3500', + 'eras_to_be_stable' => '1', + 'voting_eras_to_vote' => '1', + 'voting_eras_since_redmark' => '1', + 'uptime_calc_size' => '3500', + 'uptime_warning' => '75', + 'uptime_probation' => '70', + 'uptime_correction_unit' => 'Weeks', + 'uptime_correction_value' => '1', + 'redmarks_revoke' => '500', + 'redmarks_revoke_calc_size' => '3500', + 'responsiveness_warning' => '1', + 'responsiveness_probation' => '1' + ]; + + foreach ($names as $name => $value) { + $setting = Setting::where('name', $name)->first(); + if (!$setting) { + $setting = new Setting; + $setting->name = $name; + $setting->value = $value; + $setting->save(); + } + } + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + // + } +} diff --git a/app/Http/Controllers/Api/V1/InstallController.php b/database/migrations/2022_11_22_175343_add_data_to_emailer.php similarity index 71% rename from app/Http/Controllers/Api/V1/InstallController.php rename to database/migrations/2022_11_22_175343_add_data_to_emailer.php index 30ab5429..71e7a30e 100644 --- a/app/Http/Controllers/Api/V1/InstallController.php +++ b/database/migrations/2022_11_22_175343_add_data_to_emailer.php @@ -1,43 +1,21 @@ '50', - ]; - foreach ($names as $name => $value) { - $setting = Setting::where('name', $name)->first(); - if (!$setting) { - $setting = new Setting; - $setting->name = $name; - $setting->value = $value; - $setting->save(); - } - } - echo "Setting created
"; - } - - public function installEmailer() { - - // Setup User $userData = [ [ 'title' => 'Welcome to the Casper Association portal', @@ -64,24 +42,34 @@ public function installEmailer() { 'subject' => 'User [email] has uploaded a letter of motivation', 'content' => 'Excellent work! You have completed all the required steps to access the member\'s dashboard.

Please log in to explore. You now have access to the following:
- Node and network metrics
- Discussion previews
- Viewing previous votes

To fully unlock your dashboard\'s features, you will need to verify yourself inside the portal. This will grant you the Casper Red Checkmark, proving to the network that you are a Verified Member worthy of a higher level of trust. This process is free and takes only 5 minutes of your time.

Verified Members access all membership perks more likely to be trusted by the public for staking delegation and even get access to a public profile. It\'s a very fast process to upgrade to a Verified Member. Just look for the get verified links on the dashboard.

Verified Members can do the following:
- Start and participate in member discussions
- Vote on protocol updates or changes
- Display a page to verify their status to the public
- Access member benefits and perks
- View all network and node metrics
- Easily view details earnings from staking
- Track all health metrics for their node
' ], + [ + 'title' => 'New Perk Created', + 'subject' => 'A new perk has been added to the portal', + 'content' => '"[perk]" is now available in the portal. Please log in and view this perk on the Perks tab.' + ], + [ + 'title' => 'New Vote Started', + 'subject' => 'A new vote is live in the Casper Members portal', + 'content' => 'Voting has started for "[vote]". Please log in to the Casper Membership portal and submit your vote on the Votes tab.' + ], + [ + 'title' => '24hr Vote Reminder', + 'subject' => 'We need your vote', + 'content' => 'Only 24 hours are left in the vote titled "[vote]". Please log in and submit your vote.' + ] ]; - EmailerTriggerUser::where('id', '>', 0)->delete(); - - if (count($userData)) { - foreach ($userData as $item) { - $record = EmailerTriggerUser::where('title', $item['title'])->first(); - if ($record) $record->delete(); - - $record = new EmailerTriggerUser; - $record->title = $item['title']; - $record->subject = $item['subject']; - $record->content = $item['content']; - $record->save(); - } + foreach ($userData as $item) { + $record = EmailerTriggerUser::where('title', $item['title'])->first(); + if (!$record) { + $record = new EmailerTriggerUser; + $record->title = $item['title']; + $record->subject = $item['subject']; + $record->content = $item['content']; + $record->save(); + } } - - // Setup Admin + $adminData = [ [ 'title' => 'User uploads a letter', @@ -92,22 +80,28 @@ public function installEmailer() { 'title' => 'KYC or AML need review', 'subject' => 'KYC or AML for [name] needs review', 'content' => 'Please log in to the portal and go to the lower "Verifications" table in the Admin\'s "Intake" tab. You must click the review button next to user [name] to review this users information and select a further action based on the organization\'s guidelines' - ], + ] ]; - EmailerTriggerAdmin::where('id', '>', 0)->delete(); - - if (count($adminData)) { - foreach ($adminData as $item) { - $record = EmailerTriggerAdmin::where('title', $item['title'])->first(); - if ($record) $record->delete(); - - $record = new EmailerTriggerAdmin; - $record->title = $item['title']; - $record->subject = $item['subject']; - $record->content = $item['content']; - $record->save(); - } + foreach ($adminData as $item) { + $record = EmailerTriggerAdmin::where('title', $item['title'])->first(); + if (!$record) { + $record = new EmailerTriggerAdmin; + $record->title = $item['title']; + $record->subject = $item['subject']; + $record->content = $item['content']; + $record->save(); + } } } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + // + } } diff --git a/database/migrations/2022_11_23_030335_create_upgrades_table.php b/database/migrations/2022_11_23_030335_create_upgrades_table.php new file mode 100644 index 00000000..41c3e503 --- /dev/null +++ b/database/migrations/2022_11_23_030335_create_upgrades_table.php @@ -0,0 +1,37 @@ +id(); + $table->string('version', 255)->nullable(); + $table->date('activation_date')->nullable(); + $table->timestamp('activation_datetime')->nullable(); + $table->bigInteger('activation_era')->nullable(); + $table->string('link', 255)->nullable(); + $table->text('notes')->nullable(); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::dropIfExists('upgrades'); + } +} diff --git a/database/migrations/2021_07_11_023901_update_profile3_table.php b/database/migrations/2022_11_23_034054_update_upgrades_table.php similarity index 69% rename from database/migrations/2021_07_11_023901_update_profile3_table.php rename to database/migrations/2022_11_23_034054_update_upgrades_table.php index 12f558de..8312eb32 100644 --- a/database/migrations/2021_07_11_023901_update_profile3_table.php +++ b/database/migrations/2022_11_23_034054_update_upgrades_table.php @@ -4,7 +4,7 @@ use Illuminate\Database\Schema\Blueprint; use Illuminate\Support\Facades\Schema; -class UpdateProfile3Table extends Migration +class UpdateUpgradesTable extends Migration { /** * Run the migrations. @@ -13,8 +13,8 @@ class UpdateProfile3Table extends Migration */ public function up() { - Schema::table('profile', function ($table) { - $table->timestamp('document_verified_at')->nullable(); + Schema::table('upgrades', function (Blueprint $table) { + $table->boolean('reminder_24_sent')->default(false); }); } diff --git a/database/migrations/2021_06_09_065904_change_column_name_forumn.php b/database/migrations/2022_11_23_085214_create_upgrade_users_table.php similarity index 54% rename from database/migrations/2021_06_09_065904_change_column_name_forumn.php rename to database/migrations/2022_11_23_085214_create_upgrade_users_table.php index 87d63e0d..a4066993 100644 --- a/database/migrations/2021_06_09_065904_change_column_name_forumn.php +++ b/database/migrations/2022_11_23_085214_create_upgrade_users_table.php @@ -4,7 +4,7 @@ use Illuminate\Database\Schema\Blueprint; use Illuminate\Support\Facades\Schema; -class ChangeColumnNameForumn extends Migration +class CreateUpgradeUsersTable extends Migration { /** * Run the migrations. @@ -13,8 +13,11 @@ class ChangeColumnNameForumn extends Migration */ public function up() { - Schema::table('users', function (Blueprint $table) { - $table->renameColumn('forumn', 'pseudonym'); + Schema::create('upgrade_users', function (Blueprint $table) { + $table->id(); + $table->integer('upgrade_id'); + $table->integer('user_id'); + $table->timestamps(); }); } @@ -25,8 +28,6 @@ public function up() */ public function down() { - Schema::table('users', function (Blueprint $table) { - $table->renameColumn('pseudonym', 'forumn'); - }); + Schema::dropIfExists('upgrade_users'); } } diff --git a/database/migrations/2022_11_23_171224_add_data_to_emailer_2.php b/database/migrations/2022_11_23_171224_add_data_to_emailer_2.php new file mode 100644 index 00000000..0ee45574 --- /dev/null +++ b/database/migrations/2022_11_23_171224_add_data_to_emailer_2.php @@ -0,0 +1,52 @@ + 'User goes on probation', + 'subject' => 'Your membership is on probation', + 'content' => 'Your membership with the Casper Association is on probation. Login and view your membership tab to see why.' + ], + [ + 'title' => 'User membership is revoked', + 'subject' => 'Your membership has been revoked', + 'content' => 'Your membership with the Casper Association has been revoked. Login to see the reason why.' + ] + ]; + + foreach ($userData as $item) { + $record = EmailerTriggerUser::where('title', $item['title'])->first(); + if (!$record) { + $record = new EmailerTriggerUser; + $record->title = $item['title']; + $record->subject = $item['subject']; + $record->content = $item['content']; + $record->save(); + } + } + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + // + } +} diff --git a/public/vendor/horizon/app-dark.css b/public/vendor/horizon/app-dark.css new file mode 100644 index 00000000..00520878 --- /dev/null +++ b/public/vendor/horizon/app-dark.css @@ -0,0 +1,8 @@ +@charset "UTF-8";.vjs-tree{font-family:Monaco,Menlo,Consolas,Bitstream Vera Sans Mono,monospace!important}.vjs-tree.is-root{position:relative}.vjs-tree .vjs-tree__content{padding-left:1em}.vjs-tree .vjs-tree__content.has-line{border-left:1px dotted hsla(0,0%,80%,.28)!important}.vjs-tree .vjs-tree__brackets{cursor:pointer}.vjs-tree .vjs-tree__brackets:hover{color:#20a0ff}.vjs-tree .vjs-value__boolean,.vjs-tree .vjs-value__null,.vjs-tree .vjs-value__number{color:#a291f5!important}.vjs-tree .vjs-value__string{color:#dacb4d!important} + +/*! + * Bootstrap v4.6.2 (https://getbootstrap.com/) + * Copyright 2011-2022 The Bootstrap Authors + * Copyright 2011-2022 Twitter, Inc. + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) + */:root{--blue:#007bff;--indigo:#6610f2;--purple:#6f42c1;--pink:#e83e8c;--red:#dc3545;--orange:#fd7e14;--yellow:#ffc107;--green:#28a745;--teal:#20c997;--cyan:#17a2b8;--white:#fff;--gray:#6c757d;--gray-dark:#494444;--primary:#adadff;--secondary:#494444;--success:#1f9d55;--info:#1c3d5a;--warning:#b08d2f;--danger:#aa2e28;--light:#f8f9fa;--dark:#494444;--breakpoint-xs:0;--breakpoint-sm:2px;--breakpoint-md:8px;--breakpoint-lg:9px;--breakpoint-xl:10px;--font-family-sans-serif:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,"Noto Sans","Liberation Sans",sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";--font-family-monospace:SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace}*,:after,:before{box-sizing:border-box}html{-webkit-text-size-adjust:100%;-webkit-tap-highlight-color:rgba(0,0,0,0);font-family:sans-serif;line-height:1.15}article,aside,figcaption,figure,footer,header,hgroup,main,nav,section{display:block}body{background-color:#1c1c1c;color:#e2edf4;font-family:Nunito;font-size:.95rem;font-weight:400;line-height:1.5;margin:0;text-align:left}[tabindex="-1"]:focus:not(:focus-visible){outline:0!important}hr{box-sizing:content-box;height:0;overflow:visible}h1,h2,h3,h4,h5,h6{margin-bottom:.5rem;margin-top:0}p{margin-bottom:1rem;margin-top:0}abbr[data-original-title],abbr[title]{border-bottom:0;cursor:help;text-decoration:underline;-webkit-text-decoration:underline dotted;text-decoration:underline dotted;-webkit-text-decoration-skip-ink:none;text-decoration-skip-ink:none}address{font-style:normal;line-height:inherit}address,dl,ol,ul{margin-bottom:1rem}dl,ol,ul{margin-top:0}ol ol,ol ul,ul ol,ul ul{margin-bottom:0}dt{font-weight:700}dd{margin-bottom:.5rem;margin-left:0}blockquote{margin:0 0 1rem}b,strong{font-weight:bolder}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}a{background-color:transparent;color:#adadff;text-decoration:none}a:hover{color:#6161ff;text-decoration:underline}a:not([href]):not([class]),a:not([href]):not([class]):hover{color:inherit;text-decoration:none}code,kbd,pre,samp{font-family:SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-size:1em}pre{-ms-overflow-style:scrollbar;margin-bottom:1rem;margin-top:0;overflow:auto}figure{margin:0 0 1rem}img{border-style:none}img,svg{vertical-align:middle}svg{overflow:hidden}table{border-collapse:collapse}caption{caption-side:bottom;color:#6c757d;padding-bottom:.75rem;padding-top:.75rem;text-align:left}th{text-align:inherit;text-align:-webkit-match-parent}label{display:inline-block;margin-bottom:.5rem}button{border-radius:0}button:focus:not(:focus-visible){outline:0}button,input,optgroup,select,textarea{font-family:inherit;font-size:inherit;line-height:inherit;margin:0}button,input{overflow:visible}button,select{text-transform:none}[role=button]{cursor:pointer}select{word-wrap:normal}[type=button],[type=reset],[type=submit],button{-webkit-appearance:button}[type=button]:not(:disabled),[type=reset]:not(:disabled),[type=submit]:not(:disabled),button:not(:disabled){cursor:pointer}[type=button]::-moz-focus-inner,[type=reset]::-moz-focus-inner,[type=submit]::-moz-focus-inner,button::-moz-focus-inner{border-style:none;padding:0}input[type=checkbox],input[type=radio]{box-sizing:border-box;padding:0}textarea{overflow:auto;resize:vertical}fieldset{border:0;margin:0;min-width:0;padding:0}legend{color:inherit;display:block;font-size:1.5rem;line-height:inherit;margin-bottom:.5rem;max-width:100%;padding:0;white-space:normal;width:100%}progress{vertical-align:baseline}[type=number]::-webkit-inner-spin-button,[type=number]::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:none;outline-offset:-2px}[type=search]::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}output{display:inline-block}summary{cursor:pointer;display:list-item}template{display:none}[hidden]{display:none!important}.h1,.h2,.h3,.h4,.h5,.h6,h1,h2,h3,h4,h5,h6{font-weight:500;line-height:1.2;margin-bottom:.5rem}.h1,h1{font-size:2.375rem}.h2,h2{font-size:1.9rem}.h3,h3{font-size:1.6625rem}.h4,h4{font-size:1.425rem}.h5,h5{font-size:1.1875rem}.h6,h6{font-size:.95rem}.lead{font-size:1.1875rem;font-weight:300}.display-1{font-size:6rem}.display-1,.display-2{font-weight:300;line-height:1.2}.display-2{font-size:5.5rem}.display-3{font-size:4.5rem}.display-3,.display-4{font-weight:300;line-height:1.2}.display-4{font-size:3.5rem}hr{border:0;border-top:1px solid rgba(0,0,0,.1);margin-bottom:1rem;margin-top:1rem}.small,small{font-size:.875em;font-weight:400}.mark,mark{background-color:#fcf8e3;padding:.2em}.list-inline,.list-unstyled{list-style:none;padding-left:0}.list-inline-item{display:inline-block}.list-inline-item:not(:last-child){margin-right:.5rem}.initialism{font-size:90%;text-transform:uppercase}.blockquote{font-size:1.1875rem;margin-bottom:1rem}.blockquote-footer{color:#6c757d;display:block;font-size:.875em}.blockquote-footer:before{content:"— "}.img-fluid,.img-thumbnail{height:auto;max-width:100%}.img-thumbnail{background-color:#1c1c1c;border:1px solid #dee2e6;border-radius:.25rem;padding:.25rem}.figure{display:inline-block}.figure-img{line-height:1;margin-bottom:.5rem}.figure-caption{color:#6c757d;font-size:90%}code{word-wrap:break-word;color:#e83e8c;font-size:87.5%}a>code{color:inherit}kbd{background-color:#212529;border-radius:.2rem;color:#fff;font-size:87.5%;padding:.2rem .4rem}kbd kbd{font-size:100%;font-weight:700;padding:0}pre{color:#212529;display:block;font-size:87.5%}pre code{color:inherit;font-size:inherit;word-break:normal}.pre-scrollable{max-height:340px;overflow-y:scroll}.container,.container-fluid,.container-lg,.container-md,.container-sm,.container-xl{margin-left:auto;margin-right:auto;padding-left:15px;padding-right:15px;width:100%}@media (min-width:2px){.container,.container-sm{max-width:1137px}}@media (min-width:8px){.container,.container-md,.container-sm{max-width:1138px}}@media (min-width:9px){.container,.container-lg,.container-md,.container-sm{max-width:1139px}}@media (min-width:10px){.container,.container-lg,.container-md,.container-sm,.container-xl{max-width:1140px}}.row{display:flex;flex-wrap:wrap;margin-left:-15px;margin-right:-15px}.no-gutters{margin-left:0;margin-right:0}.no-gutters>.col,.no-gutters>[class*=col-]{padding-left:0;padding-right:0}.col,.col-1,.col-10,.col-11,.col-12,.col-2,.col-3,.col-4,.col-5,.col-6,.col-7,.col-8,.col-9,.col-auto,.col-lg,.col-lg-1,.col-lg-10,.col-lg-11,.col-lg-12,.col-lg-2,.col-lg-3,.col-lg-4,.col-lg-5,.col-lg-6,.col-lg-7,.col-lg-8,.col-lg-9,.col-lg-auto,.col-md,.col-md-1,.col-md-10,.col-md-11,.col-md-12,.col-md-2,.col-md-3,.col-md-4,.col-md-5,.col-md-6,.col-md-7,.col-md-8,.col-md-9,.col-md-auto,.col-sm,.col-sm-1,.col-sm-10,.col-sm-11,.col-sm-12,.col-sm-2,.col-sm-3,.col-sm-4,.col-sm-5,.col-sm-6,.col-sm-7,.col-sm-8,.col-sm-9,.col-sm-auto,.col-xl,.col-xl-1,.col-xl-10,.col-xl-11,.col-xl-12,.col-xl-2,.col-xl-3,.col-xl-4,.col-xl-5,.col-xl-6,.col-xl-7,.col-xl-8,.col-xl-9,.col-xl-auto{padding-left:15px;padding-right:15px;position:relative;width:100%}.col{flex-basis:0;flex-grow:1;max-width:100%}.row-cols-1>*{flex:0 0 100%;max-width:100%}.row-cols-2>*{flex:0 0 50%;max-width:50%}.row-cols-3>*{flex:0 0 33.3333333333%;max-width:33.3333333333%}.row-cols-4>*{flex:0 0 25%;max-width:25%}.row-cols-5>*{flex:0 0 20%;max-width:20%}.row-cols-6>*{flex:0 0 16.6666666667%;max-width:16.6666666667%}.col-auto{flex:0 0 auto;max-width:100%;width:auto}.col-1{flex:0 0 8.33333333%;max-width:8.33333333%}.col-2{flex:0 0 16.66666667%;max-width:16.66666667%}.col-3{flex:0 0 25%;max-width:25%}.col-4{flex:0 0 33.33333333%;max-width:33.33333333%}.col-5{flex:0 0 41.66666667%;max-width:41.66666667%}.col-6{flex:0 0 50%;max-width:50%}.col-7{flex:0 0 58.33333333%;max-width:58.33333333%}.col-8{flex:0 0 66.66666667%;max-width:66.66666667%}.col-9{flex:0 0 75%;max-width:75%}.col-10{flex:0 0 83.33333333%;max-width:83.33333333%}.col-11{flex:0 0 91.66666667%;max-width:91.66666667%}.col-12{flex:0 0 100%;max-width:100%}.order-first{order:-1}.order-last{order:13}.order-0{order:0}.order-1{order:1}.order-2{order:2}.order-3{order:3}.order-4{order:4}.order-5{order:5}.order-6{order:6}.order-7{order:7}.order-8{order:8}.order-9{order:9}.order-10{order:10}.order-11{order:11}.order-12{order:12}.offset-1{margin-left:8.33333333%}.offset-2{margin-left:16.66666667%}.offset-3{margin-left:25%}.offset-4{margin-left:33.33333333%}.offset-5{margin-left:41.66666667%}.offset-6{margin-left:50%}.offset-7{margin-left:58.33333333%}.offset-8{margin-left:66.66666667%}.offset-9{margin-left:75%}.offset-10{margin-left:83.33333333%}.offset-11{margin-left:91.66666667%}@media (min-width:2px){.col-sm{flex-basis:0;flex-grow:1;max-width:100%}.row-cols-sm-1>*{flex:0 0 100%;max-width:100%}.row-cols-sm-2>*{flex:0 0 50%;max-width:50%}.row-cols-sm-3>*{flex:0 0 33.3333333333%;max-width:33.3333333333%}.row-cols-sm-4>*{flex:0 0 25%;max-width:25%}.row-cols-sm-5>*{flex:0 0 20%;max-width:20%}.row-cols-sm-6>*{flex:0 0 16.6666666667%;max-width:16.6666666667%}.col-sm-auto{flex:0 0 auto;max-width:100%;width:auto}.col-sm-1{flex:0 0 8.33333333%;max-width:8.33333333%}.col-sm-2{flex:0 0 16.66666667%;max-width:16.66666667%}.col-sm-3{flex:0 0 25%;max-width:25%}.col-sm-4{flex:0 0 33.33333333%;max-width:33.33333333%}.col-sm-5{flex:0 0 41.66666667%;max-width:41.66666667%}.col-sm-6{flex:0 0 50%;max-width:50%}.col-sm-7{flex:0 0 58.33333333%;max-width:58.33333333%}.col-sm-8{flex:0 0 66.66666667%;max-width:66.66666667%}.col-sm-9{flex:0 0 75%;max-width:75%}.col-sm-10{flex:0 0 83.33333333%;max-width:83.33333333%}.col-sm-11{flex:0 0 91.66666667%;max-width:91.66666667%}.col-sm-12{flex:0 0 100%;max-width:100%}.order-sm-first{order:-1}.order-sm-last{order:13}.order-sm-0{order:0}.order-sm-1{order:1}.order-sm-2{order:2}.order-sm-3{order:3}.order-sm-4{order:4}.order-sm-5{order:5}.order-sm-6{order:6}.order-sm-7{order:7}.order-sm-8{order:8}.order-sm-9{order:9}.order-sm-10{order:10}.order-sm-11{order:11}.order-sm-12{order:12}.offset-sm-0{margin-left:0}.offset-sm-1{margin-left:8.33333333%}.offset-sm-2{margin-left:16.66666667%}.offset-sm-3{margin-left:25%}.offset-sm-4{margin-left:33.33333333%}.offset-sm-5{margin-left:41.66666667%}.offset-sm-6{margin-left:50%}.offset-sm-7{margin-left:58.33333333%}.offset-sm-8{margin-left:66.66666667%}.offset-sm-9{margin-left:75%}.offset-sm-10{margin-left:83.33333333%}.offset-sm-11{margin-left:91.66666667%}}@media (min-width:8px){.col-md{flex-basis:0;flex-grow:1;max-width:100%}.row-cols-md-1>*{flex:0 0 100%;max-width:100%}.row-cols-md-2>*{flex:0 0 50%;max-width:50%}.row-cols-md-3>*{flex:0 0 33.3333333333%;max-width:33.3333333333%}.row-cols-md-4>*{flex:0 0 25%;max-width:25%}.row-cols-md-5>*{flex:0 0 20%;max-width:20%}.row-cols-md-6>*{flex:0 0 16.6666666667%;max-width:16.6666666667%}.col-md-auto{flex:0 0 auto;max-width:100%;width:auto}.col-md-1{flex:0 0 8.33333333%;max-width:8.33333333%}.col-md-2{flex:0 0 16.66666667%;max-width:16.66666667%}.col-md-3{flex:0 0 25%;max-width:25%}.col-md-4{flex:0 0 33.33333333%;max-width:33.33333333%}.col-md-5{flex:0 0 41.66666667%;max-width:41.66666667%}.col-md-6{flex:0 0 50%;max-width:50%}.col-md-7{flex:0 0 58.33333333%;max-width:58.33333333%}.col-md-8{flex:0 0 66.66666667%;max-width:66.66666667%}.col-md-9{flex:0 0 75%;max-width:75%}.col-md-10{flex:0 0 83.33333333%;max-width:83.33333333%}.col-md-11{flex:0 0 91.66666667%;max-width:91.66666667%}.col-md-12{flex:0 0 100%;max-width:100%}.order-md-first{order:-1}.order-md-last{order:13}.order-md-0{order:0}.order-md-1{order:1}.order-md-2{order:2}.order-md-3{order:3}.order-md-4{order:4}.order-md-5{order:5}.order-md-6{order:6}.order-md-7{order:7}.order-md-8{order:8}.order-md-9{order:9}.order-md-10{order:10}.order-md-11{order:11}.order-md-12{order:12}.offset-md-0{margin-left:0}.offset-md-1{margin-left:8.33333333%}.offset-md-2{margin-left:16.66666667%}.offset-md-3{margin-left:25%}.offset-md-4{margin-left:33.33333333%}.offset-md-5{margin-left:41.66666667%}.offset-md-6{margin-left:50%}.offset-md-7{margin-left:58.33333333%}.offset-md-8{margin-left:66.66666667%}.offset-md-9{margin-left:75%}.offset-md-10{margin-left:83.33333333%}.offset-md-11{margin-left:91.66666667%}}@media (min-width:9px){.col-lg{flex-basis:0;flex-grow:1;max-width:100%}.row-cols-lg-1>*{flex:0 0 100%;max-width:100%}.row-cols-lg-2>*{flex:0 0 50%;max-width:50%}.row-cols-lg-3>*{flex:0 0 33.3333333333%;max-width:33.3333333333%}.row-cols-lg-4>*{flex:0 0 25%;max-width:25%}.row-cols-lg-5>*{flex:0 0 20%;max-width:20%}.row-cols-lg-6>*{flex:0 0 16.6666666667%;max-width:16.6666666667%}.col-lg-auto{flex:0 0 auto;max-width:100%;width:auto}.col-lg-1{flex:0 0 8.33333333%;max-width:8.33333333%}.col-lg-2{flex:0 0 16.66666667%;max-width:16.66666667%}.col-lg-3{flex:0 0 25%;max-width:25%}.col-lg-4{flex:0 0 33.33333333%;max-width:33.33333333%}.col-lg-5{flex:0 0 41.66666667%;max-width:41.66666667%}.col-lg-6{flex:0 0 50%;max-width:50%}.col-lg-7{flex:0 0 58.33333333%;max-width:58.33333333%}.col-lg-8{flex:0 0 66.66666667%;max-width:66.66666667%}.col-lg-9{flex:0 0 75%;max-width:75%}.col-lg-10{flex:0 0 83.33333333%;max-width:83.33333333%}.col-lg-11{flex:0 0 91.66666667%;max-width:91.66666667%}.col-lg-12{flex:0 0 100%;max-width:100%}.order-lg-first{order:-1}.order-lg-last{order:13}.order-lg-0{order:0}.order-lg-1{order:1}.order-lg-2{order:2}.order-lg-3{order:3}.order-lg-4{order:4}.order-lg-5{order:5}.order-lg-6{order:6}.order-lg-7{order:7}.order-lg-8{order:8}.order-lg-9{order:9}.order-lg-10{order:10}.order-lg-11{order:11}.order-lg-12{order:12}.offset-lg-0{margin-left:0}.offset-lg-1{margin-left:8.33333333%}.offset-lg-2{margin-left:16.66666667%}.offset-lg-3{margin-left:25%}.offset-lg-4{margin-left:33.33333333%}.offset-lg-5{margin-left:41.66666667%}.offset-lg-6{margin-left:50%}.offset-lg-7{margin-left:58.33333333%}.offset-lg-8{margin-left:66.66666667%}.offset-lg-9{margin-left:75%}.offset-lg-10{margin-left:83.33333333%}.offset-lg-11{margin-left:91.66666667%}}@media (min-width:10px){.col-xl{flex-basis:0;flex-grow:1;max-width:100%}.row-cols-xl-1>*{flex:0 0 100%;max-width:100%}.row-cols-xl-2>*{flex:0 0 50%;max-width:50%}.row-cols-xl-3>*{flex:0 0 33.3333333333%;max-width:33.3333333333%}.row-cols-xl-4>*{flex:0 0 25%;max-width:25%}.row-cols-xl-5>*{flex:0 0 20%;max-width:20%}.row-cols-xl-6>*{flex:0 0 16.6666666667%;max-width:16.6666666667%}.col-xl-auto{flex:0 0 auto;max-width:100%;width:auto}.col-xl-1{flex:0 0 8.33333333%;max-width:8.33333333%}.col-xl-2{flex:0 0 16.66666667%;max-width:16.66666667%}.col-xl-3{flex:0 0 25%;max-width:25%}.col-xl-4{flex:0 0 33.33333333%;max-width:33.33333333%}.col-xl-5{flex:0 0 41.66666667%;max-width:41.66666667%}.col-xl-6{flex:0 0 50%;max-width:50%}.col-xl-7{flex:0 0 58.33333333%;max-width:58.33333333%}.col-xl-8{flex:0 0 66.66666667%;max-width:66.66666667%}.col-xl-9{flex:0 0 75%;max-width:75%}.col-xl-10{flex:0 0 83.33333333%;max-width:83.33333333%}.col-xl-11{flex:0 0 91.66666667%;max-width:91.66666667%}.col-xl-12{flex:0 0 100%;max-width:100%}.order-xl-first{order:-1}.order-xl-last{order:13}.order-xl-0{order:0}.order-xl-1{order:1}.order-xl-2{order:2}.order-xl-3{order:3}.order-xl-4{order:4}.order-xl-5{order:5}.order-xl-6{order:6}.order-xl-7{order:7}.order-xl-8{order:8}.order-xl-9{order:9}.order-xl-10{order:10}.order-xl-11{order:11}.order-xl-12{order:12}.offset-xl-0{margin-left:0}.offset-xl-1{margin-left:8.33333333%}.offset-xl-2{margin-left:16.66666667%}.offset-xl-3{margin-left:25%}.offset-xl-4{margin-left:33.33333333%}.offset-xl-5{margin-left:41.66666667%}.offset-xl-6{margin-left:50%}.offset-xl-7{margin-left:58.33333333%}.offset-xl-8{margin-left:66.66666667%}.offset-xl-9{margin-left:75%}.offset-xl-10{margin-left:83.33333333%}.offset-xl-11{margin-left:91.66666667%}}.table{color:#e2edf4;margin-bottom:1rem;width:100%}.table td,.table th{border-top:1px solid #343434;padding:.75rem;vertical-align:top}.table thead th{border-bottom:2px solid #343434;vertical-align:bottom}.table tbody+tbody{border-top:2px solid #343434}.table-sm td,.table-sm th{padding:.3rem}.table-bordered,.table-bordered td,.table-bordered th{border:1px solid #343434}.table-bordered thead td,.table-bordered thead th{border-bottom-width:2px}.table-borderless tbody+tbody,.table-borderless td,.table-borderless th,.table-borderless thead th{border:0}.table-striped tbody tr:nth-of-type(odd){background-color:rgba(0,0,0,.05)}.table-hover tbody tr:hover{background-color:#343434;color:#e2edf4}.table-primary,.table-primary>td,.table-primary>th{background-color:#e8e8ff}.table-primary tbody+tbody,.table-primary td,.table-primary th,.table-primary thead th{border-color:#d4d4ff}.table-hover .table-primary:hover,.table-hover .table-primary:hover>td,.table-hover .table-primary:hover>th{background-color:#cfcfff}.table-secondary,.table-secondary>td,.table-secondary>th{background-color:#cccbcb}.table-secondary tbody+tbody,.table-secondary td,.table-secondary th,.table-secondary thead th{border-color:#a09e9e}.table-hover .table-secondary:hover,.table-hover .table-secondary:hover>td,.table-hover .table-secondary:hover>th{background-color:#bfbebe}.table-success,.table-success>td,.table-success>th{background-color:#c0e4cf}.table-success tbody+tbody,.table-success td,.table-success th,.table-success thead th{border-color:#8bcca7}.table-hover .table-success:hover,.table-hover .table-success:hover>td,.table-hover .table-success:hover>th{background-color:#aedcc1}.table-info,.table-info>td,.table-info>th{background-color:#bfc9d1}.table-info tbody+tbody,.table-info td,.table-info th,.table-info thead th{border-color:#899aa9}.table-hover .table-info:hover,.table-hover .table-info:hover>td,.table-hover .table-info:hover>th{background-color:#b0bcc6}.table-warning,.table-warning>td,.table-warning>th{background-color:#e9dfc5}.table-warning tbody+tbody,.table-warning td,.table-warning th,.table-warning thead th{border-color:#d6c493}.table-hover .table-warning:hover,.table-hover .table-warning:hover>td,.table-hover .table-warning:hover>th{background-color:#e2d5b3}.table-danger,.table-danger>td,.table-danger>th{background-color:#e7c4c3}.table-danger tbody+tbody,.table-danger td,.table-danger th,.table-danger thead th{border-color:#d3928f}.table-hover .table-danger:hover,.table-hover .table-danger:hover>td,.table-hover .table-danger:hover>th{background-color:#e0b2b1}.table-light,.table-light>td,.table-light>th{background-color:#fdfdfe}.table-light tbody+tbody,.table-light td,.table-light th,.table-light thead th{border-color:#fbfcfc}.table-hover .table-light:hover,.table-hover .table-light:hover>td,.table-hover .table-light:hover>th{background-color:#ececf6}.table-dark,.table-dark>td,.table-dark>th{background-color:#cccbcb}.table-dark tbody+tbody,.table-dark td,.table-dark th,.table-dark thead th{border-color:#a09e9e}.table-hover .table-dark:hover,.table-hover .table-dark:hover>td,.table-hover .table-dark:hover>th{background-color:#bfbebe}.table-active,.table-active>td,.table-active>th{background-color:#343434}.table-hover .table-active:hover,.table-hover .table-active:hover>td,.table-hover .table-active:hover>th{background-color:#272727}.table .thead-dark th{background-color:#494444;border-color:#5d5656;color:#fff}.table .thead-light th{background-color:#e9ecef;border-color:#343434;color:#495057}.table-dark{background-color:#494444;color:#fff}.table-dark td,.table-dark th,.table-dark thead th{border-color:#5d5656}.table-dark.table-bordered{border:0}.table-dark.table-striped tbody tr:nth-of-type(odd){background-color:hsla(0,0%,100%,.05)}.table-dark.table-hover tbody tr:hover{background-color:hsla(0,0%,100%,.075);color:#fff}@media (max-width:1.98px){.table-responsive-sm{-webkit-overflow-scrolling:touch;display:block;overflow-x:auto;width:100%}.table-responsive-sm>.table-bordered{border:0}}@media (max-width:7.98px){.table-responsive-md{-webkit-overflow-scrolling:touch;display:block;overflow-x:auto;width:100%}.table-responsive-md>.table-bordered{border:0}}@media (max-width:8.98px){.table-responsive-lg{-webkit-overflow-scrolling:touch;display:block;overflow-x:auto;width:100%}.table-responsive-lg>.table-bordered{border:0}}@media (max-width:9.98px){.table-responsive-xl{-webkit-overflow-scrolling:touch;display:block;overflow-x:auto;width:100%}.table-responsive-xl>.table-bordered{border:0}}.table-responsive{-webkit-overflow-scrolling:touch;display:block;overflow-x:auto;width:100%}.table-responsive>.table-bordered{border:0}.form-control{background-clip:padding-box;background-color:#242424;border:1px solid #343434;border-radius:.25rem;color:#e2edf4;display:block;font-size:.95rem;font-weight:400;height:calc(1.5em + .75rem + 2px);line-height:1.5;padding:.375rem .75rem;transition:border-color .15s ease-in-out,box-shadow .15s ease-in-out;width:100%}@media (prefers-reduced-motion:reduce){.form-control{transition:none}}.form-control::-ms-expand{background-color:transparent;border:0}.form-control:focus{background-color:#242424;border-color:#fff;box-shadow:0 0 0 .2rem rgba(173,173,255,.25);color:#e2edf4;outline:0}.form-control::-moz-placeholder{color:#6c757d;opacity:1}.form-control::placeholder{color:#6c757d;opacity:1}.form-control:disabled,.form-control[readonly]{background-color:#e9ecef;opacity:1}input[type=date].form-control,input[type=datetime-local].form-control,input[type=month].form-control,input[type=time].form-control{-webkit-appearance:none;-moz-appearance:none;appearance:none}select.form-control:-moz-focusring{color:transparent;text-shadow:0 0 0 #e2edf4}select.form-control:focus::-ms-value{background-color:#242424;color:#e2edf4}.form-control-file,.form-control-range{display:block;width:100%}.col-form-label{font-size:inherit;line-height:1.5;margin-bottom:0;padding-bottom:calc(.375rem + 1px);padding-top:calc(.375rem + 1px)}.col-form-label-lg{font-size:1.1875rem;line-height:1.5;padding-bottom:calc(.5rem + 1px);padding-top:calc(.5rem + 1px)}.col-form-label-sm{font-size:.83125rem;line-height:1.5;padding-bottom:calc(.25rem + 1px);padding-top:calc(.25rem + 1px)}.form-control-plaintext{background-color:transparent;border:solid transparent;border-width:1px 0;color:#e2edf4;display:block;font-size:.95rem;line-height:1.5;margin-bottom:0;padding:.375rem 0;width:100%}.form-control-plaintext.form-control-lg,.form-control-plaintext.form-control-sm{padding-left:0;padding-right:0}.form-control-sm{border-radius:.2rem;font-size:.83125rem;height:calc(1.5em + .5rem + 2px);line-height:1.5;padding:.25rem .5rem}.form-control-lg{border-radius:.3rem;font-size:1.1875rem;height:calc(1.5em + 1rem + 2px);line-height:1.5;padding:.5rem 1rem}select.form-control[multiple],select.form-control[size],textarea.form-control{height:auto}.form-group{margin-bottom:1rem}.form-text{display:block;margin-top:.25rem}.form-row{display:flex;flex-wrap:wrap;margin-left:-5px;margin-right:-5px}.form-row>.col,.form-row>[class*=col-]{padding-left:5px;padding-right:5px}.form-check{display:block;padding-left:1.25rem;position:relative}.form-check-input{margin-left:-1.25rem;margin-top:.3rem;position:absolute}.form-check-input:disabled~.form-check-label,.form-check-input[disabled]~.form-check-label{color:#6c757d}.form-check-label{margin-bottom:0}.form-check-inline{align-items:center;display:inline-flex;margin-right:.75rem;padding-left:0}.form-check-inline .form-check-input{margin-left:0;margin-right:.3125rem;margin-top:0;position:static}.valid-feedback{color:#1f9d55;display:none;font-size:.875em;margin-top:.25rem;width:100%}.valid-tooltip{background-color:rgba(31,157,85,.9);border-radius:.25rem;color:#fff;display:none;font-size:.83125rem;left:0;line-height:1.5;margin-top:.1rem;max-width:100%;padding:.25rem .5rem;position:absolute;top:100%;z-index:5}.form-row>.col>.valid-tooltip,.form-row>[class*=col-]>.valid-tooltip{left:5px}.is-valid~.valid-feedback,.is-valid~.valid-tooltip,.was-validated :valid~.valid-feedback,.was-validated :valid~.valid-tooltip{display:block}.form-control.is-valid,.was-validated .form-control:valid{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='8' height='8'%3E%3Cpath fill='%231f9d55' d='M2.3 6.73.6 4.53c-.4-1.04.46-1.4 1.1-.8l1.1 1.4 3.4-3.8c.6-.63 1.6-.27 1.2.7l-4 4.6c-.43.5-.8.4-1.1.1z'/%3E%3C/svg%3E");background-position:right calc(.375em + .1875rem) center;background-repeat:no-repeat;background-size:calc(.75em + .375rem) calc(.75em + .375rem);border-color:#1f9d55;padding-right:calc(1.5em + .75rem)!important}.form-control.is-valid:focus,.was-validated .form-control:valid:focus{border-color:#1f9d55;box-shadow:0 0 0 .2rem rgba(31,157,85,.25)}.was-validated select.form-control:valid,select.form-control.is-valid{background-position:right 1.5rem center;padding-right:3rem!important}.was-validated textarea.form-control:valid,textarea.form-control.is-valid{background-position:top calc(.375em + .1875rem) right calc(.375em + .1875rem);padding-right:calc(1.5em + .75rem)}.custom-select.is-valid,.was-validated .custom-select:valid{background:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='4' height='5'%3E%3Cpath fill='%23494444' d='M2 0 0 2h4zm0 5L0 3h4z'/%3E%3C/svg%3E") right .75rem center/8px 10px no-repeat,#242424 url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='8' height='8'%3E%3Cpath fill='%231f9d55' d='M2.3 6.73.6 4.53c-.4-1.04.46-1.4 1.1-.8l1.1 1.4 3.4-3.8c.6-.63 1.6-.27 1.2.7l-4 4.6c-.43.5-.8.4-1.1.1z'/%3E%3C/svg%3E") center right 1.75rem/calc(.75em + .375rem) calc(.75em + .375rem) no-repeat;border-color:#1f9d55;padding-right:calc(.75em + 2.3125rem)!important}.custom-select.is-valid:focus,.was-validated .custom-select:valid:focus{border-color:#1f9d55;box-shadow:0 0 0 .2rem rgba(31,157,85,.25)}.form-check-input.is-valid~.form-check-label,.was-validated .form-check-input:valid~.form-check-label{color:#1f9d55}.form-check-input.is-valid~.valid-feedback,.form-check-input.is-valid~.valid-tooltip,.was-validated .form-check-input:valid~.valid-feedback,.was-validated .form-check-input:valid~.valid-tooltip{display:block}.custom-control-input.is-valid~.custom-control-label,.was-validated .custom-control-input:valid~.custom-control-label{color:#1f9d55}.custom-control-input.is-valid~.custom-control-label:before,.was-validated .custom-control-input:valid~.custom-control-label:before{border-color:#1f9d55}.custom-control-input.is-valid:checked~.custom-control-label:before,.was-validated .custom-control-input:valid:checked~.custom-control-label:before{background-color:#27c86c;border-color:#27c86c}.custom-control-input.is-valid:focus~.custom-control-label:before,.was-validated .custom-control-input:valid:focus~.custom-control-label:before{box-shadow:0 0 0 .2rem rgba(31,157,85,.25)}.custom-control-input.is-valid:focus:not(:checked)~.custom-control-label:before,.was-validated .custom-control-input:valid:focus:not(:checked)~.custom-control-label:before{border-color:#1f9d55}.custom-file-input.is-valid~.custom-file-label,.was-validated .custom-file-input:valid~.custom-file-label{border-color:#1f9d55}.custom-file-input.is-valid:focus~.custom-file-label,.was-validated .custom-file-input:valid:focus~.custom-file-label{border-color:#1f9d55;box-shadow:0 0 0 .2rem rgba(31,157,85,.25)}.invalid-feedback{color:#aa2e28;display:none;font-size:.875em;margin-top:.25rem;width:100%}.invalid-tooltip{background-color:rgba(170,46,40,.9);border-radius:.25rem;color:#fff;display:none;font-size:.83125rem;left:0;line-height:1.5;margin-top:.1rem;max-width:100%;padding:.25rem .5rem;position:absolute;top:100%;z-index:5}.form-row>.col>.invalid-tooltip,.form-row>[class*=col-]>.invalid-tooltip{left:5px}.is-invalid~.invalid-feedback,.is-invalid~.invalid-tooltip,.was-validated :invalid~.invalid-feedback,.was-validated :invalid~.invalid-tooltip{display:block}.form-control.is-invalid,.was-validated .form-control:invalid{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' fill='none' stroke='%23aa2e28'%3E%3Ccircle cx='6' cy='6' r='4.5'/%3E%3Cpath stroke-linejoin='round' d='M5.8 3.6h.4L6 6.5z'/%3E%3Ccircle cx='6' cy='8.2' r='.6' fill='%23aa2e28' stroke='none'/%3E%3C/svg%3E");background-position:right calc(.375em + .1875rem) center;background-repeat:no-repeat;background-size:calc(.75em + .375rem) calc(.75em + .375rem);border-color:#aa2e28;padding-right:calc(1.5em + .75rem)!important}.form-control.is-invalid:focus,.was-validated .form-control:invalid:focus{border-color:#aa2e28;box-shadow:0 0 0 .2rem rgba(170,46,40,.25)}.was-validated select.form-control:invalid,select.form-control.is-invalid{background-position:right 1.5rem center;padding-right:3rem!important}.was-validated textarea.form-control:invalid,textarea.form-control.is-invalid{background-position:top calc(.375em + .1875rem) right calc(.375em + .1875rem);padding-right:calc(1.5em + .75rem)}.custom-select.is-invalid,.was-validated .custom-select:invalid{background:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='4' height='5'%3E%3Cpath fill='%23494444' d='M2 0 0 2h4zm0 5L0 3h4z'/%3E%3C/svg%3E") right .75rem center/8px 10px no-repeat,#242424 url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' fill='none' stroke='%23aa2e28'%3E%3Ccircle cx='6' cy='6' r='4.5'/%3E%3Cpath stroke-linejoin='round' d='M5.8 3.6h.4L6 6.5z'/%3E%3Ccircle cx='6' cy='8.2' r='.6' fill='%23aa2e28' stroke='none'/%3E%3C/svg%3E") center right 1.75rem/calc(.75em + .375rem) calc(.75em + .375rem) no-repeat;border-color:#aa2e28;padding-right:calc(.75em + 2.3125rem)!important}.custom-select.is-invalid:focus,.was-validated .custom-select:invalid:focus{border-color:#aa2e28;box-shadow:0 0 0 .2rem rgba(170,46,40,.25)}.form-check-input.is-invalid~.form-check-label,.was-validated .form-check-input:invalid~.form-check-label{color:#aa2e28}.form-check-input.is-invalid~.invalid-feedback,.form-check-input.is-invalid~.invalid-tooltip,.was-validated .form-check-input:invalid~.invalid-feedback,.was-validated .form-check-input:invalid~.invalid-tooltip{display:block}.custom-control-input.is-invalid~.custom-control-label,.was-validated .custom-control-input:invalid~.custom-control-label{color:#aa2e28}.custom-control-input.is-invalid~.custom-control-label:before,.was-validated .custom-control-input:invalid~.custom-control-label:before{border-color:#aa2e28}.custom-control-input.is-invalid:checked~.custom-control-label:before,.was-validated .custom-control-input:invalid:checked~.custom-control-label:before{background-color:#d03d35;border-color:#d03d35}.custom-control-input.is-invalid:focus~.custom-control-label:before,.was-validated .custom-control-input:invalid:focus~.custom-control-label:before{box-shadow:0 0 0 .2rem rgba(170,46,40,.25)}.custom-control-input.is-invalid:focus:not(:checked)~.custom-control-label:before,.was-validated .custom-control-input:invalid:focus:not(:checked)~.custom-control-label:before{border-color:#aa2e28}.custom-file-input.is-invalid~.custom-file-label,.was-validated .custom-file-input:invalid~.custom-file-label{border-color:#aa2e28}.custom-file-input.is-invalid:focus~.custom-file-label,.was-validated .custom-file-input:invalid:focus~.custom-file-label{border-color:#aa2e28;box-shadow:0 0 0 .2rem rgba(170,46,40,.25)}.form-inline{align-items:center;display:flex;flex-flow:row wrap}.form-inline .form-check{width:100%}@media (min-width:2px){.form-inline label{justify-content:center}.form-inline .form-group,.form-inline label{align-items:center;display:flex;margin-bottom:0}.form-inline .form-group{flex:0 0 auto;flex-flow:row wrap}.form-inline .form-control{display:inline-block;vertical-align:middle;width:auto}.form-inline .form-control-plaintext{display:inline-block}.form-inline .custom-select,.form-inline .input-group{width:auto}.form-inline .form-check{align-items:center;display:flex;justify-content:center;padding-left:0;width:auto}.form-inline .form-check-input{flex-shrink:0;margin-left:0;margin-right:.25rem;margin-top:0;position:relative}.form-inline .custom-control{align-items:center;justify-content:center}.form-inline .custom-control-label{margin-bottom:0}}.btn{background-color:transparent;border:1px solid transparent;border-radius:.25rem;color:#e2edf4;display:inline-block;font-size:.95rem;font-weight:400;line-height:1.5;padding:.375rem .75rem;text-align:center;transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;-webkit-user-select:none;-moz-user-select:none;user-select:none;vertical-align:middle}@media (prefers-reduced-motion:reduce){.btn{transition:none}}.btn:hover{color:#e2edf4;text-decoration:none}.btn.focus,.btn:focus{box-shadow:0 0 0 .2rem rgba(173,173,255,.25);outline:0}.btn.disabled,.btn:disabled{opacity:.65}.btn:not(:disabled):not(.disabled){cursor:pointer}a.btn.disabled,fieldset:disabled a.btn{pointer-events:none}.btn-primary{background-color:#adadff;border-color:#adadff;color:#212529}.btn-primary.focus,.btn-primary:focus,.btn-primary:hover{background-color:#8787ff;border-color:#7a7aff;color:#fff}.btn-primary.focus,.btn-primary:focus{box-shadow:0 0 0 .2rem rgba(152,153,223,.5)}.btn-primary.disabled,.btn-primary:disabled{background-color:#adadff;border-color:#adadff;color:#212529}.btn-primary:not(:disabled):not(.disabled).active,.btn-primary:not(:disabled):not(.disabled):active,.show>.btn-primary.dropdown-toggle{background-color:#7a7aff;border-color:#6d6dff;color:#fff}.btn-primary:not(:disabled):not(.disabled).active:focus,.btn-primary:not(:disabled):not(.disabled):active:focus,.show>.btn-primary.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(152,153,223,.5)}.btn-secondary{background-color:#494444;border-color:#494444;color:#fff}.btn-secondary.focus,.btn-secondary:focus,.btn-secondary:hover{background-color:#353232;border-color:#2f2b2b;color:#fff}.btn-secondary.focus,.btn-secondary:focus{box-shadow:0 0 0 .2rem hsla(0,2%,38%,.5)}.btn-secondary.disabled,.btn-secondary:disabled{background-color:#494444;border-color:#494444;color:#fff}.btn-secondary:not(:disabled):not(.disabled).active,.btn-secondary:not(:disabled):not(.disabled):active,.show>.btn-secondary.dropdown-toggle{background-color:#2f2b2b;border-color:#282525;color:#fff}.btn-secondary:not(:disabled):not(.disabled).active:focus,.btn-secondary:not(:disabled):not(.disabled):active:focus,.show>.btn-secondary.dropdown-toggle:focus{box-shadow:0 0 0 .2rem hsla(0,2%,38%,.5)}.btn-success{background-color:#1f9d55;border-color:#1f9d55;color:#fff}.btn-success.focus,.btn-success:focus,.btn-success:hover{background-color:#197d44;border-color:#17723e;color:#fff}.btn-success.focus,.btn-success:focus{box-shadow:0 0 0 .2rem rgba(65,172,111,.5)}.btn-success.disabled,.btn-success:disabled{background-color:#1f9d55;border-color:#1f9d55;color:#fff}.btn-success:not(:disabled):not(.disabled).active,.btn-success:not(:disabled):not(.disabled):active,.show>.btn-success.dropdown-toggle{background-color:#17723e;border-color:#146838;color:#fff}.btn-success:not(:disabled):not(.disabled).active:focus,.btn-success:not(:disabled):not(.disabled):active:focus,.show>.btn-success.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(65,172,111,.5)}.btn-info{background-color:#1c3d5a;border-color:#1c3d5a;color:#fff}.btn-info.focus,.btn-info:focus,.btn-info:hover{background-color:#13293d;border-color:#102333;color:#fff}.btn-info.focus,.btn-info:focus{box-shadow:0 0 0 .2rem rgba(62,90,115,.5)}.btn-info.disabled,.btn-info:disabled{background-color:#1c3d5a;border-color:#1c3d5a;color:#fff}.btn-info:not(:disabled):not(.disabled).active,.btn-info:not(:disabled):not(.disabled):active,.show>.btn-info.dropdown-toggle{background-color:#102333;border-color:#0d1c29;color:#fff}.btn-info:not(:disabled):not(.disabled).active:focus,.btn-info:not(:disabled):not(.disabled):active:focus,.show>.btn-info.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(62,90,115,.5)}.btn-warning{background-color:#b08d2f;border-color:#b08d2f;color:#fff}.btn-warning.focus,.btn-warning:focus,.btn-warning:hover{background-color:#927527;border-color:#886d24;color:#fff}.btn-warning.focus,.btn-warning:focus{box-shadow:0 0 0 .2rem rgba(188,158,78,.5)}.btn-warning.disabled,.btn-warning:disabled{background-color:#b08d2f;border-color:#b08d2f;color:#fff}.btn-warning:not(:disabled):not(.disabled).active,.btn-warning:not(:disabled):not(.disabled):active,.show>.btn-warning.dropdown-toggle{background-color:#886d24;border-color:#7e6522;color:#fff}.btn-warning:not(:disabled):not(.disabled).active:focus,.btn-warning:not(:disabled):not(.disabled):active:focus,.show>.btn-warning.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(188,158,78,.5)}.btn-danger{background-color:#aa2e28;border-color:#aa2e28;color:#fff}.btn-danger.focus,.btn-danger:focus,.btn-danger:hover{background-color:#8b2621;border-color:#81231e;color:#fff}.btn-danger.focus,.btn-danger:focus{box-shadow:0 0 0 .2rem rgba(183,77,72,.5)}.btn-danger.disabled,.btn-danger:disabled{background-color:#aa2e28;border-color:#aa2e28;color:#fff}.btn-danger:not(:disabled):not(.disabled).active,.btn-danger:not(:disabled):not(.disabled):active,.show>.btn-danger.dropdown-toggle{background-color:#81231e;border-color:#76201c;color:#fff}.btn-danger:not(:disabled):not(.disabled).active:focus,.btn-danger:not(:disabled):not(.disabled):active:focus,.show>.btn-danger.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(183,77,72,.5)}.btn-light{background-color:#f8f9fa;border-color:#f8f9fa;color:#212529}.btn-light.focus,.btn-light:focus,.btn-light:hover{background-color:#e2e6ea;border-color:#dae0e5;color:#212529}.btn-light.focus,.btn-light:focus{box-shadow:0 0 0 .2rem hsla(220,4%,85%,.5)}.btn-light.disabled,.btn-light:disabled{background-color:#f8f9fa;border-color:#f8f9fa;color:#212529}.btn-light:not(:disabled):not(.disabled).active,.btn-light:not(:disabled):not(.disabled):active,.show>.btn-light.dropdown-toggle{background-color:#dae0e5;border-color:#d3d9df;color:#212529}.btn-light:not(:disabled):not(.disabled).active:focus,.btn-light:not(:disabled):not(.disabled):active:focus,.show>.btn-light.dropdown-toggle:focus{box-shadow:0 0 0 .2rem hsla(220,4%,85%,.5)}.btn-dark{background-color:#494444;border-color:#494444;color:#fff}.btn-dark.focus,.btn-dark:focus,.btn-dark:hover{background-color:#353232;border-color:#2f2b2b;color:#fff}.btn-dark.focus,.btn-dark:focus{box-shadow:0 0 0 .2rem hsla(0,2%,38%,.5)}.btn-dark.disabled,.btn-dark:disabled{background-color:#494444;border-color:#494444;color:#fff}.btn-dark:not(:disabled):not(.disabled).active,.btn-dark:not(:disabled):not(.disabled):active,.show>.btn-dark.dropdown-toggle{background-color:#2f2b2b;border-color:#282525;color:#fff}.btn-dark:not(:disabled):not(.disabled).active:focus,.btn-dark:not(:disabled):not(.disabled):active:focus,.show>.btn-dark.dropdown-toggle:focus{box-shadow:0 0 0 .2rem hsla(0,2%,38%,.5)}.btn-outline-primary{border-color:#adadff;color:#adadff}.btn-outline-primary:hover{background-color:#adadff;border-color:#adadff;color:#212529}.btn-outline-primary.focus,.btn-outline-primary:focus{box-shadow:0 0 0 .2rem rgba(173,173,255,.5)}.btn-outline-primary.disabled,.btn-outline-primary:disabled{background-color:transparent;color:#adadff}.btn-outline-primary:not(:disabled):not(.disabled).active,.btn-outline-primary:not(:disabled):not(.disabled):active,.show>.btn-outline-primary.dropdown-toggle{background-color:#adadff;border-color:#adadff;color:#212529}.btn-outline-primary:not(:disabled):not(.disabled).active:focus,.btn-outline-primary:not(:disabled):not(.disabled):active:focus,.show>.btn-outline-primary.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(173,173,255,.5)}.btn-outline-secondary{border-color:#494444;color:#494444}.btn-outline-secondary:hover{background-color:#494444;border-color:#494444;color:#fff}.btn-outline-secondary.focus,.btn-outline-secondary:focus{box-shadow:0 0 0 .2rem rgba(73,68,68,.5)}.btn-outline-secondary.disabled,.btn-outline-secondary:disabled{background-color:transparent;color:#494444}.btn-outline-secondary:not(:disabled):not(.disabled).active,.btn-outline-secondary:not(:disabled):not(.disabled):active,.show>.btn-outline-secondary.dropdown-toggle{background-color:#494444;border-color:#494444;color:#fff}.btn-outline-secondary:not(:disabled):not(.disabled).active:focus,.btn-outline-secondary:not(:disabled):not(.disabled):active:focus,.show>.btn-outline-secondary.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(73,68,68,.5)}.btn-outline-success{border-color:#1f9d55;color:#1f9d55}.btn-outline-success:hover{background-color:#1f9d55;border-color:#1f9d55;color:#fff}.btn-outline-success.focus,.btn-outline-success:focus{box-shadow:0 0 0 .2rem rgba(31,157,85,.5)}.btn-outline-success.disabled,.btn-outline-success:disabled{background-color:transparent;color:#1f9d55}.btn-outline-success:not(:disabled):not(.disabled).active,.btn-outline-success:not(:disabled):not(.disabled):active,.show>.btn-outline-success.dropdown-toggle{background-color:#1f9d55;border-color:#1f9d55;color:#fff}.btn-outline-success:not(:disabled):not(.disabled).active:focus,.btn-outline-success:not(:disabled):not(.disabled):active:focus,.show>.btn-outline-success.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(31,157,85,.5)}.btn-outline-info{border-color:#1c3d5a;color:#1c3d5a}.btn-outline-info:hover{background-color:#1c3d5a;border-color:#1c3d5a;color:#fff}.btn-outline-info.focus,.btn-outline-info:focus{box-shadow:0 0 0 .2rem rgba(28,61,90,.5)}.btn-outline-info.disabled,.btn-outline-info:disabled{background-color:transparent;color:#1c3d5a}.btn-outline-info:not(:disabled):not(.disabled).active,.btn-outline-info:not(:disabled):not(.disabled):active,.show>.btn-outline-info.dropdown-toggle{background-color:#1c3d5a;border-color:#1c3d5a;color:#fff}.btn-outline-info:not(:disabled):not(.disabled).active:focus,.btn-outline-info:not(:disabled):not(.disabled):active:focus,.show>.btn-outline-info.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(28,61,90,.5)}.btn-outline-warning{border-color:#b08d2f;color:#b08d2f}.btn-outline-warning:hover{background-color:#b08d2f;border-color:#b08d2f;color:#fff}.btn-outline-warning.focus,.btn-outline-warning:focus{box-shadow:0 0 0 .2rem rgba(176,141,47,.5)}.btn-outline-warning.disabled,.btn-outline-warning:disabled{background-color:transparent;color:#b08d2f}.btn-outline-warning:not(:disabled):not(.disabled).active,.btn-outline-warning:not(:disabled):not(.disabled):active,.show>.btn-outline-warning.dropdown-toggle{background-color:#b08d2f;border-color:#b08d2f;color:#fff}.btn-outline-warning:not(:disabled):not(.disabled).active:focus,.btn-outline-warning:not(:disabled):not(.disabled):active:focus,.show>.btn-outline-warning.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(176,141,47,.5)}.btn-outline-danger{border-color:#aa2e28;color:#aa2e28}.btn-outline-danger:hover{background-color:#aa2e28;border-color:#aa2e28;color:#fff}.btn-outline-danger.focus,.btn-outline-danger:focus{box-shadow:0 0 0 .2rem rgba(170,46,40,.5)}.btn-outline-danger.disabled,.btn-outline-danger:disabled{background-color:transparent;color:#aa2e28}.btn-outline-danger:not(:disabled):not(.disabled).active,.btn-outline-danger:not(:disabled):not(.disabled):active,.show>.btn-outline-danger.dropdown-toggle{background-color:#aa2e28;border-color:#aa2e28;color:#fff}.btn-outline-danger:not(:disabled):not(.disabled).active:focus,.btn-outline-danger:not(:disabled):not(.disabled):active:focus,.show>.btn-outline-danger.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(170,46,40,.5)}.btn-outline-light{border-color:#f8f9fa;color:#f8f9fa}.btn-outline-light:hover{background-color:#f8f9fa;border-color:#f8f9fa;color:#212529}.btn-outline-light.focus,.btn-outline-light:focus{box-shadow:0 0 0 .2rem rgba(248,249,250,.5)}.btn-outline-light.disabled,.btn-outline-light:disabled{background-color:transparent;color:#f8f9fa}.btn-outline-light:not(:disabled):not(.disabled).active,.btn-outline-light:not(:disabled):not(.disabled):active,.show>.btn-outline-light.dropdown-toggle{background-color:#f8f9fa;border-color:#f8f9fa;color:#212529}.btn-outline-light:not(:disabled):not(.disabled).active:focus,.btn-outline-light:not(:disabled):not(.disabled):active:focus,.show>.btn-outline-light.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(248,249,250,.5)}.btn-outline-dark{border-color:#494444;color:#494444}.btn-outline-dark:hover{background-color:#494444;border-color:#494444;color:#fff}.btn-outline-dark.focus,.btn-outline-dark:focus{box-shadow:0 0 0 .2rem rgba(73,68,68,.5)}.btn-outline-dark.disabled,.btn-outline-dark:disabled{background-color:transparent;color:#494444}.btn-outline-dark:not(:disabled):not(.disabled).active,.btn-outline-dark:not(:disabled):not(.disabled):active,.show>.btn-outline-dark.dropdown-toggle{background-color:#494444;border-color:#494444;color:#fff}.btn-outline-dark:not(:disabled):not(.disabled).active:focus,.btn-outline-dark:not(:disabled):not(.disabled):active:focus,.show>.btn-outline-dark.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(73,68,68,.5)}.btn-link{color:#adadff;font-weight:400;text-decoration:none}.btn-link:hover{color:#6161ff}.btn-link.focus,.btn-link:focus,.btn-link:hover{text-decoration:underline}.btn-link.disabled,.btn-link:disabled{color:#6c757d;pointer-events:none}.btn-group-lg>.btn,.btn-lg{border-radius:.3rem;font-size:1.1875rem;line-height:1.5;padding:.5rem 1rem}.btn-group-sm>.btn,.btn-sm{border-radius:.2rem;font-size:.83125rem;line-height:1.5;padding:.25rem .5rem}.btn-block{display:block;width:100%}.btn-block+.btn-block{margin-top:.5rem}input[type=button].btn-block,input[type=reset].btn-block,input[type=submit].btn-block{width:100%}.fade{transition:opacity .15s linear}@media (prefers-reduced-motion:reduce){.fade{transition:none}}.fade:not(.show){opacity:0}.collapse:not(.show){display:none}.collapsing{height:0;overflow:hidden;position:relative;transition:height .35s ease}@media (prefers-reduced-motion:reduce){.collapsing{transition:none}}.collapsing.width{height:auto;transition:width .35s ease;width:0}@media (prefers-reduced-motion:reduce){.collapsing.width{transition:none}}.dropdown,.dropleft,.dropright,.dropup{position:relative}.dropdown-toggle{white-space:nowrap}.dropdown-toggle:after{border-bottom:0;border-left:.3em solid transparent;border-right:.3em solid transparent;border-top:.3em solid;content:"";display:inline-block;margin-left:.255em;vertical-align:.255em}.dropdown-toggle:empty:after{margin-left:0}.dropdown-menu{background-clip:padding-box;background-color:#181818;border:1px solid rgba(0,0,0,.15);border-radius:.25rem;color:#e2edf4;display:none;float:left;font-size:.95rem;left:0;list-style:none;margin:.125rem 0 0;min-width:10rem;padding:.5rem 0;position:absolute;text-align:left;top:100%;z-index:1000}.dropdown-menu-left{left:0;right:auto}.dropdown-menu-right{left:auto;right:0}@media (min-width:2px){.dropdown-menu-sm-left{left:0;right:auto}.dropdown-menu-sm-right{left:auto;right:0}}@media (min-width:8px){.dropdown-menu-md-left{left:0;right:auto}.dropdown-menu-md-right{left:auto;right:0}}@media (min-width:9px){.dropdown-menu-lg-left{left:0;right:auto}.dropdown-menu-lg-right{left:auto;right:0}}@media (min-width:10px){.dropdown-menu-xl-left{left:0;right:auto}.dropdown-menu-xl-right{left:auto;right:0}}.dropup .dropdown-menu{bottom:100%;margin-bottom:.125rem;margin-top:0;top:auto}.dropup .dropdown-toggle:after{border-bottom:.3em solid;border-left:.3em solid transparent;border-right:.3em solid transparent;border-top:0;content:"";display:inline-block;margin-left:.255em;vertical-align:.255em}.dropup .dropdown-toggle:empty:after{margin-left:0}.dropright .dropdown-menu{left:100%;margin-left:.125rem;margin-top:0;right:auto;top:0}.dropright .dropdown-toggle:after{border-bottom:.3em solid transparent;border-left:.3em solid;border-right:0;border-top:.3em solid transparent;content:"";display:inline-block;margin-left:.255em;vertical-align:.255em}.dropright .dropdown-toggle:empty:after{margin-left:0}.dropright .dropdown-toggle:after{vertical-align:0}.dropleft .dropdown-menu{left:auto;margin-right:.125rem;margin-top:0;right:100%;top:0}.dropleft .dropdown-toggle:after{content:"";display:inline-block;display:none;margin-left:.255em;vertical-align:.255em}.dropleft .dropdown-toggle:before{border-bottom:.3em solid transparent;border-right:.3em solid;border-top:.3em solid transparent;content:"";display:inline-block;margin-right:.255em;vertical-align:.255em}.dropleft .dropdown-toggle:empty:after{margin-left:0}.dropleft .dropdown-toggle:before{vertical-align:0}.dropdown-menu[x-placement^=bottom],.dropdown-menu[x-placement^=left],.dropdown-menu[x-placement^=right],.dropdown-menu[x-placement^=top]{bottom:auto;right:auto}.dropdown-divider{border-top:1px solid #e9ecef;height:0;margin:.5rem 0;overflow:hidden}.dropdown-item{background-color:transparent;border:0;clear:both;color:#fff;display:block;font-weight:400;padding:.25rem 1.5rem;text-align:inherit;white-space:nowrap;width:100%}.dropdown-item:focus,.dropdown-item:hover{background-color:#e9ecef;color:#16181b;text-decoration:none}.dropdown-item.active,.dropdown-item:active{background-color:#adadff;color:#fff;text-decoration:none}.dropdown-item.disabled,.dropdown-item:disabled{background-color:transparent;color:#adb5bd;pointer-events:none}.dropdown-menu.show{display:block}.dropdown-header{color:#6c757d;display:block;font-size:.83125rem;margin-bottom:0;padding:.5rem 1.5rem;white-space:nowrap}.dropdown-item-text{color:#fff;display:block;padding:.25rem 1.5rem}.btn-group,.btn-group-vertical{display:inline-flex;position:relative;vertical-align:middle}.btn-group-vertical>.btn,.btn-group>.btn{flex:1 1 auto;position:relative}.btn-group-vertical>.btn.active,.btn-group-vertical>.btn:active,.btn-group-vertical>.btn:focus,.btn-group-vertical>.btn:hover,.btn-group>.btn.active,.btn-group>.btn:active,.btn-group>.btn:focus,.btn-group>.btn:hover{z-index:1}.btn-toolbar{display:flex;flex-wrap:wrap;justify-content:flex-start}.btn-toolbar .input-group{width:auto}.btn-group>.btn-group:not(:first-child),.btn-group>.btn:not(:first-child){margin-left:-1px}.btn-group>.btn-group:not(:last-child)>.btn,.btn-group>.btn:not(:last-child):not(.dropdown-toggle){border-bottom-right-radius:0;border-top-right-radius:0}.btn-group>.btn-group:not(:first-child)>.btn,.btn-group>.btn:not(:first-child){border-bottom-left-radius:0;border-top-left-radius:0}.dropdown-toggle-split{padding-left:.5625rem;padding-right:.5625rem}.dropdown-toggle-split:after,.dropright .dropdown-toggle-split:after,.dropup .dropdown-toggle-split:after{margin-left:0}.dropleft .dropdown-toggle-split:before{margin-right:0}.btn-group-sm>.btn+.dropdown-toggle-split,.btn-sm+.dropdown-toggle-split{padding-left:.375rem;padding-right:.375rem}.btn-group-lg>.btn+.dropdown-toggle-split,.btn-lg+.dropdown-toggle-split{padding-left:.75rem;padding-right:.75rem}.btn-group-vertical{align-items:flex-start;flex-direction:column;justify-content:center}.btn-group-vertical>.btn,.btn-group-vertical>.btn-group{width:100%}.btn-group-vertical>.btn-group:not(:first-child),.btn-group-vertical>.btn:not(:first-child){margin-top:-1px}.btn-group-vertical>.btn-group:not(:last-child)>.btn,.btn-group-vertical>.btn:not(:last-child):not(.dropdown-toggle){border-bottom-left-radius:0;border-bottom-right-radius:0}.btn-group-vertical>.btn-group:not(:first-child)>.btn,.btn-group-vertical>.btn:not(:first-child){border-top-left-radius:0;border-top-right-radius:0}.btn-group-toggle>.btn,.btn-group-toggle>.btn-group>.btn{margin-bottom:0}.btn-group-toggle>.btn input[type=checkbox],.btn-group-toggle>.btn input[type=radio],.btn-group-toggle>.btn-group>.btn input[type=checkbox],.btn-group-toggle>.btn-group>.btn input[type=radio]{clip:rect(0,0,0,0);pointer-events:none;position:absolute}.input-group{align-items:stretch;display:flex;flex-wrap:wrap;position:relative;width:100%}.input-group>.custom-file,.input-group>.custom-select,.input-group>.form-control,.input-group>.form-control-plaintext{flex:1 1 auto;margin-bottom:0;min-width:0;position:relative;width:1%}.input-group>.custom-file+.custom-file,.input-group>.custom-file+.custom-select,.input-group>.custom-file+.form-control,.input-group>.custom-select+.custom-file,.input-group>.custom-select+.custom-select,.input-group>.custom-select+.form-control,.input-group>.form-control+.custom-file,.input-group>.form-control+.custom-select,.input-group>.form-control+.form-control,.input-group>.form-control-plaintext+.custom-file,.input-group>.form-control-plaintext+.custom-select,.input-group>.form-control-plaintext+.form-control{margin-left:-1px}.input-group>.custom-file .custom-file-input:focus~.custom-file-label,.input-group>.custom-select:focus,.input-group>.form-control:focus{z-index:3}.input-group>.custom-file .custom-file-input:focus{z-index:4}.input-group>.custom-select:not(:first-child),.input-group>.form-control:not(:first-child){border-bottom-left-radius:0;border-top-left-radius:0}.input-group>.custom-file{align-items:center;display:flex}.input-group>.custom-file:not(:last-child) .custom-file-label,.input-group>.custom-file:not(:last-child) .custom-file-label:after{border-bottom-right-radius:0;border-top-right-radius:0}.input-group>.custom-file:not(:first-child) .custom-file-label{border-bottom-left-radius:0;border-top-left-radius:0}.input-group.has-validation>.custom-file:nth-last-child(n+3) .custom-file-label,.input-group.has-validation>.custom-file:nth-last-child(n+3) .custom-file-label:after,.input-group.has-validation>.custom-select:nth-last-child(n+3),.input-group.has-validation>.form-control:nth-last-child(n+3),.input-group:not(.has-validation)>.custom-file:not(:last-child) .custom-file-label,.input-group:not(.has-validation)>.custom-file:not(:last-child) .custom-file-label:after,.input-group:not(.has-validation)>.custom-select:not(:last-child),.input-group:not(.has-validation)>.form-control:not(:last-child){border-bottom-right-radius:0;border-top-right-radius:0}.input-group-append,.input-group-prepend{display:flex}.input-group-append .btn,.input-group-prepend .btn{position:relative;z-index:2}.input-group-append .btn:focus,.input-group-prepend .btn:focus{z-index:3}.input-group-append .btn+.btn,.input-group-append .btn+.input-group-text,.input-group-append .input-group-text+.btn,.input-group-append .input-group-text+.input-group-text,.input-group-prepend .btn+.btn,.input-group-prepend .btn+.input-group-text,.input-group-prepend .input-group-text+.btn,.input-group-prepend .input-group-text+.input-group-text{margin-left:-1px}.input-group-prepend{margin-right:-1px}.input-group-append{margin-left:-1px}.input-group-text{align-items:center;background-color:#e9ecef;border:1px solid #343434;border-radius:.25rem;color:#e2edf4;display:flex;font-size:.95rem;font-weight:400;line-height:1.5;margin-bottom:0;padding:.375rem .75rem;text-align:center;white-space:nowrap}.input-group-text input[type=checkbox],.input-group-text input[type=radio]{margin-top:0}.input-group-lg>.custom-select,.input-group-lg>.form-control:not(textarea){height:calc(1.5em + 1rem + 2px)}.input-group-lg>.custom-select,.input-group-lg>.form-control,.input-group-lg>.input-group-append>.btn,.input-group-lg>.input-group-append>.input-group-text,.input-group-lg>.input-group-prepend>.btn,.input-group-lg>.input-group-prepend>.input-group-text{border-radius:.3rem;font-size:1.1875rem;line-height:1.5;padding:.5rem 1rem}.input-group-sm>.custom-select,.input-group-sm>.form-control:not(textarea){height:calc(1.5em + .5rem + 2px)}.input-group-sm>.custom-select,.input-group-sm>.form-control,.input-group-sm>.input-group-append>.btn,.input-group-sm>.input-group-append>.input-group-text,.input-group-sm>.input-group-prepend>.btn,.input-group-sm>.input-group-prepend>.input-group-text{border-radius:.2rem;font-size:.83125rem;line-height:1.5;padding:.25rem .5rem}.input-group-lg>.custom-select,.input-group-sm>.custom-select{padding-right:1.75rem}.input-group.has-validation>.input-group-append:nth-last-child(n+3)>.btn,.input-group.has-validation>.input-group-append:nth-last-child(n+3)>.input-group-text,.input-group:not(.has-validation)>.input-group-append:not(:last-child)>.btn,.input-group:not(.has-validation)>.input-group-append:not(:last-child)>.input-group-text,.input-group>.input-group-append:last-child>.btn:not(:last-child):not(.dropdown-toggle),.input-group>.input-group-append:last-child>.input-group-text:not(:last-child),.input-group>.input-group-prepend>.btn,.input-group>.input-group-prepend>.input-group-text{border-bottom-right-radius:0;border-top-right-radius:0}.input-group>.input-group-append>.btn,.input-group>.input-group-append>.input-group-text,.input-group>.input-group-prepend:first-child>.btn:not(:first-child),.input-group>.input-group-prepend:first-child>.input-group-text:not(:first-child),.input-group>.input-group-prepend:not(:first-child)>.btn,.input-group>.input-group-prepend:not(:first-child)>.input-group-text{border-bottom-left-radius:0;border-top-left-radius:0}.custom-control{display:block;min-height:1.425rem;padding-left:1.5rem;position:relative;-webkit-print-color-adjust:exact;print-color-adjust:exact;z-index:1}.custom-control-inline{display:inline-flex;margin-right:1rem}.custom-control-input{height:1.2125rem;left:0;opacity:0;position:absolute;width:1rem;z-index:-1}.custom-control-input:checked~.custom-control-label:before{background-color:#adadff;border-color:#adadff;color:#fff}.custom-control-input:focus~.custom-control-label:before{box-shadow:0 0 0 .2rem rgba(173,173,255,.25)}.custom-control-input:focus:not(:checked)~.custom-control-label:before{border-color:#fff}.custom-control-input:not(:disabled):active~.custom-control-label:before{background-color:#fff;border-color:#fff;color:#fff}.custom-control-input:disabled~.custom-control-label,.custom-control-input[disabled]~.custom-control-label{color:#6c757d}.custom-control-input:disabled~.custom-control-label:before,.custom-control-input[disabled]~.custom-control-label:before{background-color:#e9ecef}.custom-control-label{margin-bottom:0;position:relative;vertical-align:top}.custom-control-label:before{background-color:#242424;border:1px solid #adb5bd;pointer-events:none}.custom-control-label:after,.custom-control-label:before{content:"";display:block;height:1rem;left:-1.5rem;position:absolute;top:.2125rem;width:1rem}.custom-control-label:after{background:50%/50% 50% no-repeat}.custom-checkbox .custom-control-label:before{border-radius:.25rem}.custom-checkbox .custom-control-input:checked~.custom-control-label:after{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='8' height='8'%3E%3Cpath fill='%23fff' d='m6.564.75-3.59 3.612-1.538-1.55L0 4.26l2.974 2.99L8 2.193z'/%3E%3C/svg%3E")}.custom-checkbox .custom-control-input:indeterminate~.custom-control-label:before{background-color:#adadff;border-color:#adadff}.custom-checkbox .custom-control-input:indeterminate~.custom-control-label:after{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='4' height='4'%3E%3Cpath stroke='%23fff' d='M0 2h4'/%3E%3C/svg%3E")}.custom-checkbox .custom-control-input:disabled:checked~.custom-control-label:before{background-color:rgba(173,173,255,.5)}.custom-checkbox .custom-control-input:disabled:indeterminate~.custom-control-label:before{background-color:rgba(173,173,255,.5)}.custom-radio .custom-control-label:before{border-radius:50%}.custom-radio .custom-control-input:checked~.custom-control-label:after{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='-4 -4 8 8'%3E%3Ccircle r='3' fill='%23fff'/%3E%3C/svg%3E")}.custom-radio .custom-control-input:disabled:checked~.custom-control-label:before{background-color:rgba(173,173,255,.5)}.custom-switch{padding-left:2.25rem}.custom-switch .custom-control-label:before{border-radius:.5rem;left:-2.25rem;pointer-events:all;width:1.75rem}.custom-switch .custom-control-label:after{background-color:#adb5bd;border-radius:.5rem;height:calc(1rem - 4px);left:calc(-2.25rem + 2px);top:calc(.2125rem + 2px);transition:transform .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;width:calc(1rem - 4px)}@media (prefers-reduced-motion:reduce){.custom-switch .custom-control-label:after{transition:none}}.custom-switch .custom-control-input:checked~.custom-control-label:after{background-color:#242424;transform:translateX(.75rem)}.custom-switch .custom-control-input:disabled:checked~.custom-control-label:before{background-color:rgba(173,173,255,.5)}.custom-select{-webkit-appearance:none;-moz-appearance:none;appearance:none;background:#242424 url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='4' height='5'%3E%3Cpath fill='%23494444' d='M2 0 0 2h4zm0 5L0 3h4z'/%3E%3C/svg%3E") right .75rem center/8px 10px no-repeat;border:1px solid #343434;border-radius:.25rem;color:#e2edf4;display:inline-block;font-size:.95rem;font-weight:400;height:calc(1.5em + .75rem + 2px);line-height:1.5;padding:.375rem 1.75rem .375rem .75rem;vertical-align:middle;width:100%}.custom-select:focus{border-color:#fff;box-shadow:0 0 0 .2rem rgba(173,173,255,.25);outline:0}.custom-select:focus::-ms-value{background-color:#242424;color:#e2edf4}.custom-select[multiple],.custom-select[size]:not([size="1"]){background-image:none;height:auto;padding-right:.75rem}.custom-select:disabled{background-color:#e9ecef;color:#6c757d}.custom-select::-ms-expand{display:none}.custom-select:-moz-focusring{color:transparent;text-shadow:0 0 0 #e2edf4}.custom-select-sm{font-size:.83125rem;height:calc(1.5em + .5rem + 2px);padding-bottom:.25rem;padding-left:.5rem;padding-top:.25rem}.custom-select-lg{font-size:1.1875rem;height:calc(1.5em + 1rem + 2px);padding-bottom:.5rem;padding-left:1rem;padding-top:.5rem}.custom-file{display:inline-block;margin-bottom:0}.custom-file,.custom-file-input{height:calc(1.5em + .75rem + 2px);position:relative;width:100%}.custom-file-input{margin:0;opacity:0;overflow:hidden;z-index:2}.custom-file-input:focus~.custom-file-label{border-color:#fff;box-shadow:0 0 0 .2rem rgba(173,173,255,.25)}.custom-file-input:disabled~.custom-file-label,.custom-file-input[disabled]~.custom-file-label{background-color:#e9ecef}.custom-file-input:lang(en)~.custom-file-label:after{content:"Browse"}.custom-file-input~.custom-file-label[data-browse]:after{content:attr(data-browse)}.custom-file-label{background-color:#242424;border:1px solid #343434;border-radius:.25rem;font-weight:400;height:calc(1.5em + .75rem + 2px);left:0;overflow:hidden;z-index:1}.custom-file-label,.custom-file-label:after{color:#e2edf4;line-height:1.5;padding:.375rem .75rem;position:absolute;right:0;top:0}.custom-file-label:after{background-color:#e9ecef;border-left:inherit;border-radius:0 .25rem .25rem 0;bottom:0;content:"Browse";display:block;height:calc(1.5em + .75rem);z-index:3}.custom-range{-webkit-appearance:none;-moz-appearance:none;appearance:none;background-color:transparent;height:1.4rem;padding:0;width:100%}.custom-range:focus{outline:0}.custom-range:focus::-webkit-slider-thumb{box-shadow:0 0 0 1px #1c1c1c,0 0 0 .2rem rgba(173,173,255,.25)}.custom-range:focus::-moz-range-thumb{box-shadow:0 0 0 1px #1c1c1c,0 0 0 .2rem rgba(173,173,255,.25)}.custom-range:focus::-ms-thumb{box-shadow:0 0 0 1px #1c1c1c,0 0 0 .2rem rgba(173,173,255,.25)}.custom-range::-moz-focus-outer{border:0}.custom-range::-webkit-slider-thumb{-webkit-appearance:none;appearance:none;background-color:#adadff;border:0;border-radius:1rem;height:1rem;margin-top:-.25rem;-webkit-transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;width:1rem}@media (prefers-reduced-motion:reduce){.custom-range::-webkit-slider-thumb{-webkit-transition:none;transition:none}}.custom-range::-webkit-slider-thumb:active{background-color:#fff}.custom-range::-webkit-slider-runnable-track{background-color:#dee2e6;border-color:transparent;border-radius:1rem;color:transparent;cursor:pointer;height:.5rem;width:100%}.custom-range::-moz-range-thumb{-moz-appearance:none;appearance:none;background-color:#adadff;border:0;border-radius:1rem;height:1rem;-moz-transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;width:1rem}@media (prefers-reduced-motion:reduce){.custom-range::-moz-range-thumb{-moz-transition:none;transition:none}}.custom-range::-moz-range-thumb:active{background-color:#fff}.custom-range::-moz-range-track{background-color:#dee2e6;border-color:transparent;border-radius:1rem;color:transparent;cursor:pointer;height:.5rem;width:100%}.custom-range::-ms-thumb{appearance:none;background-color:#adadff;border:0;border-radius:1rem;height:1rem;margin-left:.2rem;margin-right:.2rem;margin-top:0;-ms-transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;width:1rem}@media (prefers-reduced-motion:reduce){.custom-range::-ms-thumb{-ms-transition:none;transition:none}}.custom-range::-ms-thumb:active{background-color:#fff}.custom-range::-ms-track{background-color:transparent;border-color:transparent;border-width:.5rem;color:transparent;cursor:pointer;height:.5rem;width:100%}.custom-range::-ms-fill-lower,.custom-range::-ms-fill-upper{background-color:#dee2e6;border-radius:1rem}.custom-range::-ms-fill-upper{margin-right:15px}.custom-range:disabled::-webkit-slider-thumb{background-color:#adb5bd}.custom-range:disabled::-webkit-slider-runnable-track{cursor:default}.custom-range:disabled::-moz-range-thumb{background-color:#adb5bd}.custom-range:disabled::-moz-range-track{cursor:default}.custom-range:disabled::-ms-thumb{background-color:#adb5bd}.custom-control-label:before,.custom-file-label,.custom-select{transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out}@media (prefers-reduced-motion:reduce){.custom-control-label:before,.custom-file-label,.custom-select{transition:none}}.nav{display:flex;flex-wrap:wrap;list-style:none;margin-bottom:0;padding-left:0}.nav-link{display:block;padding:.5rem 1rem}.nav-link:focus,.nav-link:hover{text-decoration:none}.nav-link.disabled{color:#6c757d;cursor:default;pointer-events:none}.nav-tabs{border-bottom:1px solid #dee2e6}.nav-tabs .nav-link{background-color:transparent;border:1px solid transparent;border-top-left-radius:.25rem;border-top-right-radius:.25rem;margin-bottom:-1px}.nav-tabs .nav-link:focus,.nav-tabs .nav-link:hover{border-color:#e9ecef #e9ecef #dee2e6;isolation:isolate}.nav-tabs .nav-link.disabled{background-color:transparent;border-color:transparent;color:#6c757d}.nav-tabs .nav-item.show .nav-link,.nav-tabs .nav-link.active{background-color:#1c1c1c;border-color:#dee2e6 #dee2e6 #1c1c1c;color:#495057}.nav-tabs .dropdown-menu{border-top-left-radius:0;border-top-right-radius:0;margin-top:-1px}.nav-pills .nav-link{background:none;border:0;border-radius:.25rem}.nav-pills .nav-link.active,.nav-pills .show>.nav-link{background-color:#adadff;color:#fff}.nav-fill .nav-item,.nav-fill>.nav-link{flex:1 1 auto;text-align:center}.nav-justified .nav-item,.nav-justified>.nav-link{flex-basis:0;flex-grow:1;text-align:center}.tab-content>.tab-pane{display:none}.tab-content>.active{display:block}.navbar{padding:.5rem 1rem;position:relative}.navbar,.navbar .container,.navbar .container-fluid,.navbar .container-lg,.navbar .container-md,.navbar .container-sm,.navbar .container-xl{align-items:center;display:flex;flex-wrap:wrap;justify-content:space-between}.navbar-brand{display:inline-block;font-size:1.1875rem;line-height:inherit;margin-right:1rem;padding-bottom:.321875rem;padding-top:.321875rem;white-space:nowrap}.navbar-brand:focus,.navbar-brand:hover{text-decoration:none}.navbar-nav{display:flex;flex-direction:column;list-style:none;margin-bottom:0;padding-left:0}.navbar-nav .nav-link{padding-left:0;padding-right:0}.navbar-nav .dropdown-menu{float:none;position:static}.navbar-text{display:inline-block;padding-bottom:.5rem;padding-top:.5rem}.navbar-collapse{align-items:center;flex-basis:100%;flex-grow:1}.navbar-toggler{background-color:transparent;border:1px solid transparent;border-radius:.25rem;font-size:1.1875rem;line-height:1;padding:.25rem .75rem}.navbar-toggler:focus,.navbar-toggler:hover{text-decoration:none}.navbar-toggler-icon{background:50%/100% 100% no-repeat;content:"";display:inline-block;height:1.5em;vertical-align:middle;width:1.5em}.navbar-nav-scroll{max-height:75vh;overflow-y:auto}@media (max-width:1.98px){.navbar-expand-sm>.container,.navbar-expand-sm>.container-fluid,.navbar-expand-sm>.container-lg,.navbar-expand-sm>.container-md,.navbar-expand-sm>.container-sm,.navbar-expand-sm>.container-xl{padding-left:0;padding-right:0}}@media (min-width:2px){.navbar-expand-sm{flex-flow:row nowrap;justify-content:flex-start}.navbar-expand-sm .navbar-nav{flex-direction:row}.navbar-expand-sm .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-sm .navbar-nav .nav-link{padding-left:.5rem;padding-right:.5rem}.navbar-expand-sm>.container,.navbar-expand-sm>.container-fluid,.navbar-expand-sm>.container-lg,.navbar-expand-sm>.container-md,.navbar-expand-sm>.container-sm,.navbar-expand-sm>.container-xl{flex-wrap:nowrap}.navbar-expand-sm .navbar-nav-scroll{overflow:visible}.navbar-expand-sm .navbar-collapse{display:flex!important;flex-basis:auto}.navbar-expand-sm .navbar-toggler{display:none}}@media (max-width:7.98px){.navbar-expand-md>.container,.navbar-expand-md>.container-fluid,.navbar-expand-md>.container-lg,.navbar-expand-md>.container-md,.navbar-expand-md>.container-sm,.navbar-expand-md>.container-xl{padding-left:0;padding-right:0}}@media (min-width:8px){.navbar-expand-md{flex-flow:row nowrap;justify-content:flex-start}.navbar-expand-md .navbar-nav{flex-direction:row}.navbar-expand-md .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-md .navbar-nav .nav-link{padding-left:.5rem;padding-right:.5rem}.navbar-expand-md>.container,.navbar-expand-md>.container-fluid,.navbar-expand-md>.container-lg,.navbar-expand-md>.container-md,.navbar-expand-md>.container-sm,.navbar-expand-md>.container-xl{flex-wrap:nowrap}.navbar-expand-md .navbar-nav-scroll{overflow:visible}.navbar-expand-md .navbar-collapse{display:flex!important;flex-basis:auto}.navbar-expand-md .navbar-toggler{display:none}}@media (max-width:8.98px){.navbar-expand-lg>.container,.navbar-expand-lg>.container-fluid,.navbar-expand-lg>.container-lg,.navbar-expand-lg>.container-md,.navbar-expand-lg>.container-sm,.navbar-expand-lg>.container-xl{padding-left:0;padding-right:0}}@media (min-width:9px){.navbar-expand-lg{flex-flow:row nowrap;justify-content:flex-start}.navbar-expand-lg .navbar-nav{flex-direction:row}.navbar-expand-lg .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-lg .navbar-nav .nav-link{padding-left:.5rem;padding-right:.5rem}.navbar-expand-lg>.container,.navbar-expand-lg>.container-fluid,.navbar-expand-lg>.container-lg,.navbar-expand-lg>.container-md,.navbar-expand-lg>.container-sm,.navbar-expand-lg>.container-xl{flex-wrap:nowrap}.navbar-expand-lg .navbar-nav-scroll{overflow:visible}.navbar-expand-lg .navbar-collapse{display:flex!important;flex-basis:auto}.navbar-expand-lg .navbar-toggler{display:none}}@media (max-width:9.98px){.navbar-expand-xl>.container,.navbar-expand-xl>.container-fluid,.navbar-expand-xl>.container-lg,.navbar-expand-xl>.container-md,.navbar-expand-xl>.container-sm,.navbar-expand-xl>.container-xl{padding-left:0;padding-right:0}}@media (min-width:10px){.navbar-expand-xl{flex-flow:row nowrap;justify-content:flex-start}.navbar-expand-xl .navbar-nav{flex-direction:row}.navbar-expand-xl .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-xl .navbar-nav .nav-link{padding-left:.5rem;padding-right:.5rem}.navbar-expand-xl>.container,.navbar-expand-xl>.container-fluid,.navbar-expand-xl>.container-lg,.navbar-expand-xl>.container-md,.navbar-expand-xl>.container-sm,.navbar-expand-xl>.container-xl{flex-wrap:nowrap}.navbar-expand-xl .navbar-nav-scroll{overflow:visible}.navbar-expand-xl .navbar-collapse{display:flex!important;flex-basis:auto}.navbar-expand-xl .navbar-toggler{display:none}}.navbar-expand{flex-flow:row nowrap;justify-content:flex-start}.navbar-expand>.container,.navbar-expand>.container-fluid,.navbar-expand>.container-lg,.navbar-expand>.container-md,.navbar-expand>.container-sm,.navbar-expand>.container-xl{padding-left:0;padding-right:0}.navbar-expand .navbar-nav{flex-direction:row}.navbar-expand .navbar-nav .dropdown-menu{position:absolute}.navbar-expand .navbar-nav .nav-link{padding-left:.5rem;padding-right:.5rem}.navbar-expand>.container,.navbar-expand>.container-fluid,.navbar-expand>.container-lg,.navbar-expand>.container-md,.navbar-expand>.container-sm,.navbar-expand>.container-xl{flex-wrap:nowrap}.navbar-expand .navbar-nav-scroll{overflow:visible}.navbar-expand .navbar-collapse{display:flex!important;flex-basis:auto}.navbar-expand .navbar-toggler{display:none}.navbar-light .navbar-brand,.navbar-light .navbar-brand:focus,.navbar-light .navbar-brand:hover{color:rgba(0,0,0,.9)}.navbar-light .navbar-nav .nav-link{color:rgba(0,0,0,.5)}.navbar-light .navbar-nav .nav-link:focus,.navbar-light .navbar-nav .nav-link:hover{color:rgba(0,0,0,.7)}.navbar-light .navbar-nav .nav-link.disabled{color:rgba(0,0,0,.3)}.navbar-light .navbar-nav .active>.nav-link,.navbar-light .navbar-nav .nav-link.active,.navbar-light .navbar-nav .nav-link.show,.navbar-light .navbar-nav .show>.nav-link{color:rgba(0,0,0,.9)}.navbar-light .navbar-toggler{border-color:rgba(0,0,0,.1);color:rgba(0,0,0,.5)}.navbar-light .navbar-toggler-icon{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='30' height='30'%3E%3Cpath stroke='rgba(0, 0, 0, 0.5)' stroke-linecap='round' stroke-miterlimit='10' stroke-width='2' d='M4 7h22M4 15h22M4 23h22'/%3E%3C/svg%3E")}.navbar-light .navbar-text{color:rgba(0,0,0,.5)}.navbar-light .navbar-text a,.navbar-light .navbar-text a:focus,.navbar-light .navbar-text a:hover{color:rgba(0,0,0,.9)}.navbar-dark .navbar-brand,.navbar-dark .navbar-brand:focus,.navbar-dark .navbar-brand:hover{color:#fff}.navbar-dark .navbar-nav .nav-link{color:hsla(0,0%,100%,.5)}.navbar-dark .navbar-nav .nav-link:focus,.navbar-dark .navbar-nav .nav-link:hover{color:hsla(0,0%,100%,.75)}.navbar-dark .navbar-nav .nav-link.disabled{color:hsla(0,0%,100%,.25)}.navbar-dark .navbar-nav .active>.nav-link,.navbar-dark .navbar-nav .nav-link.active,.navbar-dark .navbar-nav .nav-link.show,.navbar-dark .navbar-nav .show>.nav-link{color:#fff}.navbar-dark .navbar-toggler{border-color:hsla(0,0%,100%,.1);color:hsla(0,0%,100%,.5)}.navbar-dark .navbar-toggler-icon{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='30' height='30'%3E%3Cpath stroke='rgba(255, 255, 255, 0.5)' stroke-linecap='round' stroke-miterlimit='10' stroke-width='2' d='M4 7h22M4 15h22M4 23h22'/%3E%3C/svg%3E")}.navbar-dark .navbar-text{color:hsla(0,0%,100%,.5)}.navbar-dark .navbar-text a,.navbar-dark .navbar-text a:focus,.navbar-dark .navbar-text a:hover{color:#fff}.card{word-wrap:break-word;background-clip:border-box;background-color:#120f12;border:1px solid rgba(0,0,0,.125);border-radius:.25rem;display:flex;flex-direction:column;min-width:0;position:relative}.card>hr{margin-left:0;margin-right:0}.card>.list-group{border-bottom:inherit;border-top:inherit}.card>.list-group:first-child{border-top-left-radius:calc(.25rem - 1px);border-top-right-radius:calc(.25rem - 1px);border-top-width:0}.card>.list-group:last-child{border-bottom-left-radius:calc(.25rem - 1px);border-bottom-right-radius:calc(.25rem - 1px);border-bottom-width:0}.card>.card-header+.list-group,.card>.list-group+.card-footer{border-top:0}.card-body{flex:1 1 auto;min-height:1px;padding:1.25rem}.card-title{margin-bottom:.75rem}.card-subtitle{margin-top:-.375rem}.card-subtitle,.card-text:last-child{margin-bottom:0}.card-link:hover{text-decoration:none}.card-link+.card-link{margin-left:1.25rem}.card-header{background-color:#120f12;border-bottom:1px solid rgba(0,0,0,.125);margin-bottom:0;padding:.75rem 1.25rem}.card-header:first-child{border-radius:calc(.25rem - 1px) calc(.25rem - 1px) 0 0}.card-footer{background-color:#120f12;border-top:1px solid rgba(0,0,0,.125);padding:.75rem 1.25rem}.card-footer:last-child{border-radius:0 0 calc(.25rem - 1px) calc(.25rem - 1px)}.card-header-tabs{border-bottom:0;margin-bottom:-.75rem}.card-header-pills,.card-header-tabs{margin-left:-.625rem;margin-right:-.625rem}.card-img-overlay{border-radius:calc(.25rem - 1px);bottom:0;left:0;padding:1.25rem;position:absolute;right:0;top:0}.card-img,.card-img-bottom,.card-img-top{flex-shrink:0;width:100%}.card-img,.card-img-top{border-top-left-radius:calc(.25rem - 1px);border-top-right-radius:calc(.25rem - 1px)}.card-img,.card-img-bottom{border-bottom-left-radius:calc(.25rem - 1px);border-bottom-right-radius:calc(.25rem - 1px)}.card-deck .card{margin-bottom:15px}@media (min-width:2px){.card-deck{display:flex;flex-flow:row wrap;margin-left:-15px;margin-right:-15px}.card-deck .card{flex:1 0 0%;margin-bottom:0;margin-left:15px;margin-right:15px}}.card-group>.card{margin-bottom:15px}@media (min-width:2px){.card-group{display:flex;flex-flow:row wrap}.card-group>.card{flex:1 0 0%;margin-bottom:0}.card-group>.card+.card{border-left:0;margin-left:0}.card-group>.card:not(:last-child){border-bottom-right-radius:0;border-top-right-radius:0}.card-group>.card:not(:last-child) .card-header,.card-group>.card:not(:last-child) .card-img-top{border-top-right-radius:0}.card-group>.card:not(:last-child) .card-footer,.card-group>.card:not(:last-child) .card-img-bottom{border-bottom-right-radius:0}.card-group>.card:not(:first-child){border-bottom-left-radius:0;border-top-left-radius:0}.card-group>.card:not(:first-child) .card-header,.card-group>.card:not(:first-child) .card-img-top{border-top-left-radius:0}.card-group>.card:not(:first-child) .card-footer,.card-group>.card:not(:first-child) .card-img-bottom{border-bottom-left-radius:0}}.card-columns .card{margin-bottom:.75rem}@media (min-width:2px){.card-columns{-moz-column-count:3;column-count:3;-moz-column-gap:1.25rem;column-gap:1.25rem;orphans:1;widows:1}.card-columns .card{display:inline-block;width:100%}}.accordion{overflow-anchor:none}.accordion>.card{overflow:hidden}.accordion>.card:not(:last-of-type){border-bottom:0;border-bottom-left-radius:0;border-bottom-right-radius:0}.accordion>.card:not(:first-of-type){border-top-left-radius:0;border-top-right-radius:0}.accordion>.card>.card-header{border-radius:0;margin-bottom:-1px}.breadcrumb{background-color:#e9ecef;border-radius:.25rem;display:flex;flex-wrap:wrap;list-style:none;margin-bottom:1rem;padding:.75rem 1rem}.breadcrumb-item+.breadcrumb-item{padding-left:.5rem}.breadcrumb-item+.breadcrumb-item:before{color:#6c757d;content:"/";float:left;padding-right:.5rem}.breadcrumb-item+.breadcrumb-item:hover:before{text-decoration:underline;text-decoration:none}.breadcrumb-item.active{color:#6c757d}.pagination{border-radius:.25rem;display:flex;list-style:none;padding-left:0}.page-link{background-color:#fff;border:1px solid #dee2e6;color:#adadff;display:block;line-height:1.25;margin-left:-1px;padding:.5rem .75rem;position:relative}.page-link:hover{background-color:#e9ecef;border-color:#dee2e6;color:#6161ff;text-decoration:none;z-index:2}.page-link:focus{box-shadow:0 0 0 .2rem rgba(173,173,255,.25);outline:0;z-index:3}.page-item:first-child .page-link{border-bottom-left-radius:.25rem;border-top-left-radius:.25rem;margin-left:0}.page-item:last-child .page-link{border-bottom-right-radius:.25rem;border-top-right-radius:.25rem}.page-item.active .page-link{background-color:#adadff;border-color:#adadff;color:#fff;z-index:3}.page-item.disabled .page-link{background-color:#fff;border-color:#dee2e6;color:#6c757d;cursor:auto;pointer-events:none}.pagination-lg .page-link{font-size:1.1875rem;line-height:1.5;padding:.75rem 1.5rem}.pagination-lg .page-item:first-child .page-link{border-bottom-left-radius:.3rem;border-top-left-radius:.3rem}.pagination-lg .page-item:last-child .page-link{border-bottom-right-radius:.3rem;border-top-right-radius:.3rem}.pagination-sm .page-link{font-size:.83125rem;line-height:1.5;padding:.25rem .5rem}.pagination-sm .page-item:first-child .page-link{border-bottom-left-radius:.2rem;border-top-left-radius:.2rem}.pagination-sm .page-item:last-child .page-link{border-bottom-right-radius:.2rem;border-top-right-radius:.2rem}.badge{border-radius:.25rem;display:inline-block;font-size:.95rem;font-weight:700;line-height:1;padding:.25em .4em;text-align:center;transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;vertical-align:baseline;white-space:nowrap}@media (prefers-reduced-motion:reduce){.badge{transition:none}}a.badge:focus,a.badge:hover{text-decoration:none}.badge:empty{display:none}.btn .badge{position:relative;top:-1px}.badge-pill{border-radius:10rem;padding-left:.6em;padding-right:.6em}.badge-primary{background-color:#adadff;color:#212529}a.badge-primary:focus,a.badge-primary:hover{background-color:#7a7aff;color:#212529}a.badge-primary.focus,a.badge-primary:focus{box-shadow:0 0 0 .2rem rgba(173,173,255,.5);outline:0}.badge-secondary{background-color:#494444;color:#fff}a.badge-secondary:focus,a.badge-secondary:hover{background-color:#2f2b2b;color:#fff}a.badge-secondary.focus,a.badge-secondary:focus{box-shadow:0 0 0 .2rem rgba(73,68,68,.5);outline:0}.badge-success{background-color:#1f9d55;color:#fff}a.badge-success:focus,a.badge-success:hover{background-color:#17723e;color:#fff}a.badge-success.focus,a.badge-success:focus{box-shadow:0 0 0 .2rem rgba(31,157,85,.5);outline:0}.badge-info{background-color:#1c3d5a;color:#fff}a.badge-info:focus,a.badge-info:hover{background-color:#102333;color:#fff}a.badge-info.focus,a.badge-info:focus{box-shadow:0 0 0 .2rem rgba(28,61,90,.5);outline:0}.badge-warning{background-color:#b08d2f;color:#fff}a.badge-warning:focus,a.badge-warning:hover{background-color:#886d24;color:#fff}a.badge-warning.focus,a.badge-warning:focus{box-shadow:0 0 0 .2rem rgba(176,141,47,.5);outline:0}.badge-danger{background-color:#aa2e28;color:#fff}a.badge-danger:focus,a.badge-danger:hover{background-color:#81231e;color:#fff}a.badge-danger.focus,a.badge-danger:focus{box-shadow:0 0 0 .2rem rgba(170,46,40,.5);outline:0}.badge-light{background-color:#f8f9fa;color:#212529}a.badge-light:focus,a.badge-light:hover{background-color:#dae0e5;color:#212529}a.badge-light.focus,a.badge-light:focus{box-shadow:0 0 0 .2rem rgba(248,249,250,.5);outline:0}.badge-dark{background-color:#494444;color:#fff}a.badge-dark:focus,a.badge-dark:hover{background-color:#2f2b2b;color:#fff}a.badge-dark.focus,a.badge-dark:focus{box-shadow:0 0 0 .2rem rgba(73,68,68,.5);outline:0}.jumbotron{background-color:#e9ecef;border-radius:.3rem;margin-bottom:2rem;padding:2rem 1rem}@media (min-width:2px){.jumbotron{padding:4rem 2rem}}.jumbotron-fluid{border-radius:0;padding-left:0;padding-right:0}.alert{border:1px solid transparent;border-radius:.25rem;margin-bottom:1rem;padding:.75rem 1.25rem;position:relative}.alert-heading{color:inherit}.alert-link{font-weight:700}.alert-dismissible{padding-right:3.925rem}.alert-dismissible .close{color:inherit;padding:.75rem 1.25rem;position:absolute;right:0;top:0;z-index:2}.alert-primary{background-color:#efefff;border-color:#e8e8ff;color:#5a5a85}.alert-primary hr{border-top-color:#cfcfff}.alert-primary .alert-link{color:#454567}.alert-secondary{background-color:#dbdada;border-color:#cccbcb;color:#262323}.alert-secondary hr{border-top-color:#bfbebe}.alert-secondary .alert-link{color:#0b0b0b}.alert-success{background-color:#d2ebdd;border-color:#c0e4cf;color:#10522c}.alert-success hr{border-top-color:#aedcc1}.alert-success .alert-link{color:#082715}.alert-info{background-color:#d2d8de;border-color:#bfc9d1;color:#0f202f}.alert-info hr{border-top-color:#b0bcc6}.alert-info .alert-link{color:#030608}.alert-warning{background-color:#efe8d5;border-color:#e9dfc5;color:#5c4918}.alert-warning hr{border-top-color:#e2d5b3}.alert-warning .alert-link{color:#34290d}.alert-danger{background-color:#eed5d4;border-color:#e7c4c3;color:#581815}.alert-danger hr{border-top-color:#e0b2b1}.alert-danger .alert-link{color:#2f0d0b}.alert-light{background-color:#fefefe;border-color:#fdfdfe;color:#818182}.alert-light hr{border-top-color:#ececf6}.alert-light .alert-link{color:#686868}.alert-dark{background-color:#dbdada;border-color:#cccbcb;color:#262323}.alert-dark hr{border-top-color:#bfbebe}.alert-dark .alert-link{color:#0b0b0b}@keyframes progress-bar-stripes{0%{background-position:1rem 0}to{background-position:0 0}}.progress{background-color:#e9ecef;border-radius:.25rem;font-size:.7125rem;height:1rem;line-height:0}.progress,.progress-bar{display:flex;overflow:hidden}.progress-bar{background-color:#adadff;color:#fff;flex-direction:column;justify-content:center;text-align:center;transition:width .6s ease;white-space:nowrap}@media (prefers-reduced-motion:reduce){.progress-bar{transition:none}}.progress-bar-striped{background-image:linear-gradient(45deg,hsla(0,0%,100%,.15) 25%,transparent 0,transparent 50%,hsla(0,0%,100%,.15) 0,hsla(0,0%,100%,.15) 75%,transparent 0,transparent);background-size:1rem 1rem}.progress-bar-animated{animation:progress-bar-stripes 1s linear infinite}@media (prefers-reduced-motion:reduce){.progress-bar-animated{animation:none}}.media{align-items:flex-start;display:flex}.media-body{flex:1}.list-group{border-radius:.25rem;display:flex;flex-direction:column;margin-bottom:0;padding-left:0}.list-group-item-action{color:#495057;text-align:inherit;width:100%}.list-group-item-action:focus,.list-group-item-action:hover{background-color:#f8f9fa;color:#495057;text-decoration:none;z-index:1}.list-group-item-action:active{background-color:#e9ecef;color:#e2edf4}.list-group-item{background-color:#fff;border:1px solid rgba(0,0,0,.125);display:block;padding:.75rem 1.25rem;position:relative}.list-group-item:first-child{border-top-left-radius:inherit;border-top-right-radius:inherit}.list-group-item:last-child{border-bottom-left-radius:inherit;border-bottom-right-radius:inherit}.list-group-item.disabled,.list-group-item:disabled{background-color:#fff;color:#6c757d;pointer-events:none}.list-group-item.active{background-color:#adadff;border-color:#adadff;color:#fff;z-index:2}.list-group-item+.list-group-item{border-top-width:0}.list-group-item+.list-group-item.active{border-top-width:1px;margin-top:-1px}.list-group-horizontal{flex-direction:row}.list-group-horizontal>.list-group-item:first-child{border-bottom-left-radius:.25rem;border-top-right-radius:0}.list-group-horizontal>.list-group-item:last-child{border-bottom-left-radius:0;border-top-right-radius:.25rem}.list-group-horizontal>.list-group-item.active{margin-top:0}.list-group-horizontal>.list-group-item+.list-group-item{border-left-width:0;border-top-width:1px}.list-group-horizontal>.list-group-item+.list-group-item.active{border-left-width:1px;margin-left:-1px}@media (min-width:2px){.list-group-horizontal-sm{flex-direction:row}.list-group-horizontal-sm>.list-group-item:first-child{border-bottom-left-radius:.25rem;border-top-right-radius:0}.list-group-horizontal-sm>.list-group-item:last-child{border-bottom-left-radius:0;border-top-right-radius:.25rem}.list-group-horizontal-sm>.list-group-item.active{margin-top:0}.list-group-horizontal-sm>.list-group-item+.list-group-item{border-left-width:0;border-top-width:1px}.list-group-horizontal-sm>.list-group-item+.list-group-item.active{border-left-width:1px;margin-left:-1px}}@media (min-width:8px){.list-group-horizontal-md{flex-direction:row}.list-group-horizontal-md>.list-group-item:first-child{border-bottom-left-radius:.25rem;border-top-right-radius:0}.list-group-horizontal-md>.list-group-item:last-child{border-bottom-left-radius:0;border-top-right-radius:.25rem}.list-group-horizontal-md>.list-group-item.active{margin-top:0}.list-group-horizontal-md>.list-group-item+.list-group-item{border-left-width:0;border-top-width:1px}.list-group-horizontal-md>.list-group-item+.list-group-item.active{border-left-width:1px;margin-left:-1px}}@media (min-width:9px){.list-group-horizontal-lg{flex-direction:row}.list-group-horizontal-lg>.list-group-item:first-child{border-bottom-left-radius:.25rem;border-top-right-radius:0}.list-group-horizontal-lg>.list-group-item:last-child{border-bottom-left-radius:0;border-top-right-radius:.25rem}.list-group-horizontal-lg>.list-group-item.active{margin-top:0}.list-group-horizontal-lg>.list-group-item+.list-group-item{border-left-width:0;border-top-width:1px}.list-group-horizontal-lg>.list-group-item+.list-group-item.active{border-left-width:1px;margin-left:-1px}}@media (min-width:10px){.list-group-horizontal-xl{flex-direction:row}.list-group-horizontal-xl>.list-group-item:first-child{border-bottom-left-radius:.25rem;border-top-right-radius:0}.list-group-horizontal-xl>.list-group-item:last-child{border-bottom-left-radius:0;border-top-right-radius:.25rem}.list-group-horizontal-xl>.list-group-item.active{margin-top:0}.list-group-horizontal-xl>.list-group-item+.list-group-item{border-left-width:0;border-top-width:1px}.list-group-horizontal-xl>.list-group-item+.list-group-item.active{border-left-width:1px;margin-left:-1px}}.list-group-flush{border-radius:0}.list-group-flush>.list-group-item{border-width:0 0 1px}.list-group-flush>.list-group-item:last-child{border-bottom-width:0}.list-group-item-primary{background-color:#e8e8ff;color:#5a5a85}.list-group-item-primary.list-group-item-action:focus,.list-group-item-primary.list-group-item-action:hover{background-color:#cfcfff;color:#5a5a85}.list-group-item-primary.list-group-item-action.active{background-color:#5a5a85;border-color:#5a5a85;color:#fff}.list-group-item-secondary{background-color:#cccbcb;color:#262323}.list-group-item-secondary.list-group-item-action:focus,.list-group-item-secondary.list-group-item-action:hover{background-color:#bfbebe;color:#262323}.list-group-item-secondary.list-group-item-action.active{background-color:#262323;border-color:#262323;color:#fff}.list-group-item-success{background-color:#c0e4cf;color:#10522c}.list-group-item-success.list-group-item-action:focus,.list-group-item-success.list-group-item-action:hover{background-color:#aedcc1;color:#10522c}.list-group-item-success.list-group-item-action.active{background-color:#10522c;border-color:#10522c;color:#fff}.list-group-item-info{background-color:#bfc9d1;color:#0f202f}.list-group-item-info.list-group-item-action:focus,.list-group-item-info.list-group-item-action:hover{background-color:#b0bcc6;color:#0f202f}.list-group-item-info.list-group-item-action.active{background-color:#0f202f;border-color:#0f202f;color:#fff}.list-group-item-warning{background-color:#e9dfc5;color:#5c4918}.list-group-item-warning.list-group-item-action:focus,.list-group-item-warning.list-group-item-action:hover{background-color:#e2d5b3;color:#5c4918}.list-group-item-warning.list-group-item-action.active{background-color:#5c4918;border-color:#5c4918;color:#fff}.list-group-item-danger{background-color:#e7c4c3;color:#581815}.list-group-item-danger.list-group-item-action:focus,.list-group-item-danger.list-group-item-action:hover{background-color:#e0b2b1;color:#581815}.list-group-item-danger.list-group-item-action.active{background-color:#581815;border-color:#581815;color:#fff}.list-group-item-light{background-color:#fdfdfe;color:#818182}.list-group-item-light.list-group-item-action:focus,.list-group-item-light.list-group-item-action:hover{background-color:#ececf6;color:#818182}.list-group-item-light.list-group-item-action.active{background-color:#818182;border-color:#818182;color:#fff}.list-group-item-dark{background-color:#cccbcb;color:#262323}.list-group-item-dark.list-group-item-action:focus,.list-group-item-dark.list-group-item-action:hover{background-color:#bfbebe;color:#262323}.list-group-item-dark.list-group-item-action.active{background-color:#262323;border-color:#262323;color:#fff}.close{color:#000;float:right;font-size:1.425rem;font-weight:700;line-height:1;opacity:.5;text-shadow:0 1px 0 #fff}.close:hover{color:#000;text-decoration:none}.close:not(:disabled):not(.disabled):focus,.close:not(:disabled):not(.disabled):hover{opacity:.75}button.close{background-color:transparent;border:0;padding:0}a.close.disabled{pointer-events:none}.toast{background-clip:padding-box;background-color:hsla(0,0%,100%,.85);border:1px solid rgba(0,0,0,.1);border-radius:.25rem;box-shadow:0 .25rem .75rem rgba(0,0,0,.1);flex-basis:350px;font-size:.875rem;max-width:350px;opacity:0}.toast:not(:last-child){margin-bottom:.75rem}.toast.showing{opacity:1}.toast.show{display:block;opacity:1}.toast.hide{display:none}.toast-header{align-items:center;background-clip:padding-box;background-color:hsla(0,0%,100%,.85);border-bottom:1px solid rgba(0,0,0,.05);border-top-left-radius:calc(.25rem - 1px);border-top-right-radius:calc(.25rem - 1px);color:#6c757d;display:flex;padding:.25rem .75rem}.toast-body{padding:.75rem}.modal-open{overflow:hidden}.modal-open .modal{overflow-x:hidden;overflow-y:auto}.modal{display:none;height:100%;left:0;outline:0;overflow:hidden;position:fixed;top:0;width:100%;z-index:1050}.modal-dialog{margin:.5rem;pointer-events:none;position:relative;width:auto}.modal.fade .modal-dialog{transform:translateY(-50px);transition:transform .3s ease-out}@media (prefers-reduced-motion:reduce){.modal.fade .modal-dialog{transition:none}}.modal.show .modal-dialog{transform:none}.modal.modal-static .modal-dialog{transform:scale(1.02)}.modal-dialog-scrollable{display:flex;max-height:calc(100% - 1rem)}.modal-dialog-scrollable .modal-content{max-height:calc(100vh - 1rem);overflow:hidden}.modal-dialog-scrollable .modal-footer,.modal-dialog-scrollable .modal-header{flex-shrink:0}.modal-dialog-scrollable .modal-body{overflow-y:auto}.modal-dialog-centered{align-items:center;display:flex;min-height:calc(100% - 1rem)}.modal-dialog-centered:before{content:"";display:block;height:calc(100vh - 1rem);height:-moz-min-content;height:min-content}.modal-dialog-centered.modal-dialog-scrollable{flex-direction:column;height:100%;justify-content:center}.modal-dialog-centered.modal-dialog-scrollable .modal-content{max-height:none}.modal-dialog-centered.modal-dialog-scrollable:before{content:none}.modal-content{background-clip:padding-box;background-color:#181818;border:1px solid rgba(0,0,0,.2);border-radius:.3rem;display:flex;flex-direction:column;outline:0;pointer-events:auto;position:relative;width:100%}.modal-backdrop{background-color:#7e7e7e;height:100vh;left:0;position:fixed;top:0;width:100vw;z-index:1040}.modal-backdrop.fade{opacity:0}.modal-backdrop.show{opacity:.5}.modal-header{align-items:flex-start;border-bottom:1px solid #343434;border-top-left-radius:calc(.3rem - 1px);border-top-right-radius:calc(.3rem - 1px);display:flex;justify-content:space-between;padding:1rem}.modal-header .close{margin:-1rem -1rem -1rem auto;padding:1rem}.modal-title{line-height:1.5;margin-bottom:0}.modal-body{flex:1 1 auto;padding:1rem;position:relative}.modal-footer{align-items:center;border-bottom-left-radius:calc(.3rem - 1px);border-bottom-right-radius:calc(.3rem - 1px);border-top:1px solid #343434;display:flex;flex-wrap:wrap;justify-content:flex-end;padding:.75rem}.modal-footer>*{margin:.25rem}.modal-scrollbar-measure{height:50px;overflow:scroll;position:absolute;top:-9999px;width:50px}@media (min-width:2px){.modal-dialog{margin:1.75rem auto;max-width:500px}.modal-dialog-scrollable{max-height:calc(100% - 3.5rem)}.modal-dialog-scrollable .modal-content{max-height:calc(100vh - 3.5rem)}.modal-dialog-centered{min-height:calc(100% - 3.5rem)}.modal-dialog-centered:before{height:calc(100vh - 3.5rem);height:-moz-min-content;height:min-content}.modal-sm{max-width:300px}}@media (min-width:9px){.modal-lg,.modal-xl{max-width:800px}}@media (min-width:10px){.modal-xl{max-width:1140px}}.tooltip{word-wrap:break-word;display:block;font-family:Nunito;font-size:.83125rem;font-style:normal;font-weight:400;letter-spacing:normal;line-break:auto;line-height:1.5;margin:0;opacity:0;position:absolute;text-align:left;text-align:start;text-decoration:none;text-shadow:none;text-transform:none;white-space:normal;word-break:normal;word-spacing:normal;z-index:1070}.tooltip.show{opacity:.9}.tooltip .arrow{display:block;height:.4rem;position:absolute;width:.8rem}.tooltip .arrow:before{border-color:transparent;border-style:solid;content:"";position:absolute}.bs-tooltip-auto[x-placement^=top],.bs-tooltip-top{padding:.4rem 0}.bs-tooltip-auto[x-placement^=top] .arrow,.bs-tooltip-top .arrow{bottom:0}.bs-tooltip-auto[x-placement^=top] .arrow:before,.bs-tooltip-top .arrow:before{border-top-color:#000;border-width:.4rem .4rem 0;top:0}.bs-tooltip-auto[x-placement^=right],.bs-tooltip-right{padding:0 .4rem}.bs-tooltip-auto[x-placement^=right] .arrow,.bs-tooltip-right .arrow{height:.8rem;left:0;width:.4rem}.bs-tooltip-auto[x-placement^=right] .arrow:before,.bs-tooltip-right .arrow:before{border-right-color:#000;border-width:.4rem .4rem .4rem 0;right:0}.bs-tooltip-auto[x-placement^=bottom],.bs-tooltip-bottom{padding:.4rem 0}.bs-tooltip-auto[x-placement^=bottom] .arrow,.bs-tooltip-bottom .arrow{top:0}.bs-tooltip-auto[x-placement^=bottom] .arrow:before,.bs-tooltip-bottom .arrow:before{border-bottom-color:#000;border-width:0 .4rem .4rem;bottom:0}.bs-tooltip-auto[x-placement^=left],.bs-tooltip-left{padding:0 .4rem}.bs-tooltip-auto[x-placement^=left] .arrow,.bs-tooltip-left .arrow{height:.8rem;right:0;width:.4rem}.bs-tooltip-auto[x-placement^=left] .arrow:before,.bs-tooltip-left .arrow:before{border-left-color:#000;border-width:.4rem 0 .4rem .4rem;left:0}.tooltip-inner{background-color:#000;border-radius:.25rem;color:#fff;max-width:200px;padding:.25rem .5rem;text-align:center}.popover{word-wrap:break-word;background-clip:padding-box;background-color:#fff;border:1px solid rgba(0,0,0,.2);border-radius:.3rem;font-family:Nunito;font-size:.83125rem;font-style:normal;font-weight:400;left:0;letter-spacing:normal;line-break:auto;line-height:1.5;max-width:276px;text-align:left;text-align:start;text-decoration:none;text-shadow:none;text-transform:none;top:0;white-space:normal;word-break:normal;word-spacing:normal;z-index:1060}.popover,.popover .arrow{display:block;position:absolute}.popover .arrow{height:.5rem;margin:0 .3rem;width:1rem}.popover .arrow:after,.popover .arrow:before{border-color:transparent;border-style:solid;content:"";display:block;position:absolute}.bs-popover-auto[x-placement^=top],.bs-popover-top{margin-bottom:.5rem}.bs-popover-auto[x-placement^=top]>.arrow,.bs-popover-top>.arrow{bottom:calc(-.5rem - 1px)}.bs-popover-auto[x-placement^=top]>.arrow:before,.bs-popover-top>.arrow:before{border-top-color:rgba(0,0,0,.25);border-width:.5rem .5rem 0;bottom:0}.bs-popover-auto[x-placement^=top]>.arrow:after,.bs-popover-top>.arrow:after{border-top-color:#fff;border-width:.5rem .5rem 0;bottom:1px}.bs-popover-auto[x-placement^=right],.bs-popover-right{margin-left:.5rem}.bs-popover-auto[x-placement^=right]>.arrow,.bs-popover-right>.arrow{height:1rem;left:calc(-.5rem - 1px);margin:.3rem 0;width:.5rem}.bs-popover-auto[x-placement^=right]>.arrow:before,.bs-popover-right>.arrow:before{border-right-color:rgba(0,0,0,.25);border-width:.5rem .5rem .5rem 0;left:0}.bs-popover-auto[x-placement^=right]>.arrow:after,.bs-popover-right>.arrow:after{border-right-color:#fff;border-width:.5rem .5rem .5rem 0;left:1px}.bs-popover-auto[x-placement^=bottom],.bs-popover-bottom{margin-top:.5rem}.bs-popover-auto[x-placement^=bottom]>.arrow,.bs-popover-bottom>.arrow{top:calc(-.5rem - 1px)}.bs-popover-auto[x-placement^=bottom]>.arrow:before,.bs-popover-bottom>.arrow:before{border-bottom-color:rgba(0,0,0,.25);border-width:0 .5rem .5rem;top:0}.bs-popover-auto[x-placement^=bottom]>.arrow:after,.bs-popover-bottom>.arrow:after{border-bottom-color:#fff;border-width:0 .5rem .5rem;top:1px}.bs-popover-auto[x-placement^=bottom] .popover-header:before,.bs-popover-bottom .popover-header:before{border-bottom:1px solid #f7f7f7;content:"";display:block;left:50%;margin-left:-.5rem;position:absolute;top:0;width:1rem}.bs-popover-auto[x-placement^=left],.bs-popover-left{margin-right:.5rem}.bs-popover-auto[x-placement^=left]>.arrow,.bs-popover-left>.arrow{height:1rem;margin:.3rem 0;right:calc(-.5rem - 1px);width:.5rem}.bs-popover-auto[x-placement^=left]>.arrow:before,.bs-popover-left>.arrow:before{border-left-color:rgba(0,0,0,.25);border-width:.5rem 0 .5rem .5rem;right:0}.bs-popover-auto[x-placement^=left]>.arrow:after,.bs-popover-left>.arrow:after{border-left-color:#fff;border-width:.5rem 0 .5rem .5rem;right:1px}.popover-header{background-color:#f7f7f7;border-bottom:1px solid #ebebeb;border-top-left-radius:calc(.3rem - 1px);border-top-right-radius:calc(.3rem - 1px);font-size:.95rem;margin-bottom:0;padding:.5rem .75rem}.popover-header:empty{display:none}.popover-body{color:#e2edf4;padding:.5rem .75rem}.carousel{position:relative}.carousel.pointer-event{touch-action:pan-y}.carousel-inner{overflow:hidden;position:relative;width:100%}.carousel-inner:after{clear:both;content:"";display:block}.carousel-item{-webkit-backface-visibility:hidden;backface-visibility:hidden;display:none;float:left;margin-right:-100%;position:relative;transition:transform .6s ease-in-out;width:100%}@media (prefers-reduced-motion:reduce){.carousel-item{transition:none}}.carousel-item-next,.carousel-item-prev,.carousel-item.active{display:block}.active.carousel-item-right,.carousel-item-next:not(.carousel-item-left){transform:translateX(100%)}.active.carousel-item-left,.carousel-item-prev:not(.carousel-item-right){transform:translateX(-100%)}.carousel-fade .carousel-item{opacity:0;transform:none;transition-property:opacity}.carousel-fade .carousel-item-next.carousel-item-left,.carousel-fade .carousel-item-prev.carousel-item-right,.carousel-fade .carousel-item.active{opacity:1;z-index:1}.carousel-fade .active.carousel-item-left,.carousel-fade .active.carousel-item-right{opacity:0;transition:opacity 0s .6s;z-index:0}@media (prefers-reduced-motion:reduce){.carousel-fade .active.carousel-item-left,.carousel-fade .active.carousel-item-right{transition:none}}.carousel-control-next,.carousel-control-prev{align-items:center;background:none;border:0;bottom:0;color:#fff;display:flex;justify-content:center;opacity:.5;padding:0;position:absolute;text-align:center;top:0;transition:opacity .15s ease;width:15%;z-index:1}@media (prefers-reduced-motion:reduce){.carousel-control-next,.carousel-control-prev{transition:none}}.carousel-control-next:focus,.carousel-control-next:hover,.carousel-control-prev:focus,.carousel-control-prev:hover{color:#fff;opacity:.9;outline:0;text-decoration:none}.carousel-control-prev{left:0}.carousel-control-next{right:0}.carousel-control-next-icon,.carousel-control-prev-icon{background:50%/100% 100% no-repeat;display:inline-block;height:20px;width:20px}.carousel-control-prev-icon{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='%23fff' width='8' height='8'%3E%3Cpath d='m5.25 0-4 4 4 4 1.5-1.5L4.25 4l2.5-2.5L5.25 0z'/%3E%3C/svg%3E")}.carousel-control-next-icon{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='%23fff' width='8' height='8'%3E%3Cpath d='m2.75 0-1.5 1.5L3.75 4l-2.5 2.5L2.75 8l4-4-4-4z'/%3E%3C/svg%3E")}.carousel-indicators{bottom:0;display:flex;justify-content:center;left:0;list-style:none;margin-left:15%;margin-right:15%;padding-left:0;position:absolute;right:0;z-index:15}.carousel-indicators li{background-clip:padding-box;background-color:#fff;border-bottom:10px solid transparent;border-top:10px solid transparent;box-sizing:content-box;cursor:pointer;flex:0 1 auto;height:3px;margin-left:3px;margin-right:3px;opacity:.5;text-indent:-999px;transition:opacity .6s ease;width:30px}@media (prefers-reduced-motion:reduce){.carousel-indicators li{transition:none}}.carousel-indicators .active{opacity:1}.carousel-caption{bottom:20px;color:#fff;left:15%;padding-bottom:20px;padding-top:20px;position:absolute;right:15%;text-align:center;z-index:10}@keyframes spinner-border{to{transform:rotate(1turn)}}.spinner-border{animation:spinner-border .75s linear infinite;border:.25em solid;border-radius:50%;border-right:.25em solid transparent;display:inline-block;height:2rem;vertical-align:-.125em;width:2rem}.spinner-border-sm{border-width:.2em;height:1rem;width:1rem}@keyframes spinner-grow{0%{transform:scale(0)}50%{opacity:1;transform:none}}.spinner-grow{animation:spinner-grow .75s linear infinite;background-color:currentcolor;border-radius:50%;display:inline-block;height:2rem;opacity:0;vertical-align:-.125em;width:2rem}.spinner-grow-sm{height:1rem;width:1rem}@media (prefers-reduced-motion:reduce){.spinner-border,.spinner-grow{animation-duration:1.5s}}.align-baseline{vertical-align:baseline!important}.align-top{vertical-align:top!important}.align-middle{vertical-align:middle!important}.align-bottom{vertical-align:bottom!important}.align-text-bottom{vertical-align:text-bottom!important}.align-text-top{vertical-align:text-top!important}.bg-primary{background-color:#adadff!important}a.bg-primary:focus,a.bg-primary:hover,button.bg-primary:focus,button.bg-primary:hover{background-color:#7a7aff!important}.bg-secondary{background-color:#494444!important}a.bg-secondary:focus,a.bg-secondary:hover,button.bg-secondary:focus,button.bg-secondary:hover{background-color:#2f2b2b!important}.bg-success{background-color:#1f9d55!important}a.bg-success:focus,a.bg-success:hover,button.bg-success:focus,button.bg-success:hover{background-color:#17723e!important}.bg-info{background-color:#1c3d5a!important}a.bg-info:focus,a.bg-info:hover,button.bg-info:focus,button.bg-info:hover{background-color:#102333!important}.bg-warning{background-color:#b08d2f!important}a.bg-warning:focus,a.bg-warning:hover,button.bg-warning:focus,button.bg-warning:hover{background-color:#886d24!important}.bg-danger{background-color:#aa2e28!important}a.bg-danger:focus,a.bg-danger:hover,button.bg-danger:focus,button.bg-danger:hover{background-color:#81231e!important}.bg-light{background-color:#f8f9fa!important}a.bg-light:focus,a.bg-light:hover,button.bg-light:focus,button.bg-light:hover{background-color:#dae0e5!important}.bg-dark{background-color:#494444!important}a.bg-dark:focus,a.bg-dark:hover,button.bg-dark:focus,button.bg-dark:hover{background-color:#2f2b2b!important}.bg-white{background-color:#fff!important}.bg-transparent{background-color:transparent!important}.border{border:1px solid #303030!important}.border-top{border-top:1px solid #303030!important}.border-right{border-right:1px solid #303030!important}.border-bottom{border-bottom:1px solid #303030!important}.border-left{border-left:1px solid #303030!important}.border-0{border:0!important}.border-top-0{border-top:0!important}.border-right-0{border-right:0!important}.border-bottom-0{border-bottom:0!important}.border-left-0{border-left:0!important}.border-primary{border-color:#adadff!important}.border-secondary{border-color:#494444!important}.border-success{border-color:#1f9d55!important}.border-info{border-color:#1c3d5a!important}.border-warning{border-color:#b08d2f!important}.border-danger{border-color:#aa2e28!important}.border-light{border-color:#f8f9fa!important}.border-dark{border-color:#494444!important}.border-white{border-color:#fff!important}.rounded-sm{border-radius:.2rem!important}.rounded{border-radius:.25rem!important}.rounded-top{border-top-left-radius:.25rem!important}.rounded-right,.rounded-top{border-top-right-radius:.25rem!important}.rounded-bottom,.rounded-right{border-bottom-right-radius:.25rem!important}.rounded-bottom,.rounded-left{border-bottom-left-radius:.25rem!important}.rounded-left{border-top-left-radius:.25rem!important}.rounded-lg{border-radius:.3rem!important}.rounded-circle{border-radius:50%!important}.rounded-pill{border-radius:50rem!important}.rounded-0{border-radius:0!important}.clearfix:after{clear:both;content:"";display:block}.d-none{display:none!important}.d-inline{display:inline!important}.d-inline-block{display:inline-block!important}.d-block{display:block!important}.d-table{display:table!important}.d-table-row{display:table-row!important}.d-table-cell{display:table-cell!important}.d-flex{display:flex!important}.d-inline-flex{display:inline-flex!important}@media (min-width:2px){.d-sm-none{display:none!important}.d-sm-inline{display:inline!important}.d-sm-inline-block{display:inline-block!important}.d-sm-block{display:block!important}.d-sm-table{display:table!important}.d-sm-table-row{display:table-row!important}.d-sm-table-cell{display:table-cell!important}.d-sm-flex{display:flex!important}.d-sm-inline-flex{display:inline-flex!important}}@media (min-width:8px){.d-md-none{display:none!important}.d-md-inline{display:inline!important}.d-md-inline-block{display:inline-block!important}.d-md-block{display:block!important}.d-md-table{display:table!important}.d-md-table-row{display:table-row!important}.d-md-table-cell{display:table-cell!important}.d-md-flex{display:flex!important}.d-md-inline-flex{display:inline-flex!important}}@media (min-width:9px){.d-lg-none{display:none!important}.d-lg-inline{display:inline!important}.d-lg-inline-block{display:inline-block!important}.d-lg-block{display:block!important}.d-lg-table{display:table!important}.d-lg-table-row{display:table-row!important}.d-lg-table-cell{display:table-cell!important}.d-lg-flex{display:flex!important}.d-lg-inline-flex{display:inline-flex!important}}@media (min-width:10px){.d-xl-none{display:none!important}.d-xl-inline{display:inline!important}.d-xl-inline-block{display:inline-block!important}.d-xl-block{display:block!important}.d-xl-table{display:table!important}.d-xl-table-row{display:table-row!important}.d-xl-table-cell{display:table-cell!important}.d-xl-flex{display:flex!important}.d-xl-inline-flex{display:inline-flex!important}}@media print{.d-print-none{display:none!important}.d-print-inline{display:inline!important}.d-print-inline-block{display:inline-block!important}.d-print-block{display:block!important}.d-print-table{display:table!important}.d-print-table-row{display:table-row!important}.d-print-table-cell{display:table-cell!important}.d-print-flex{display:flex!important}.d-print-inline-flex{display:inline-flex!important}}.embed-responsive{display:block;overflow:hidden;padding:0;position:relative;width:100%}.embed-responsive:before{content:"";display:block}.embed-responsive .embed-responsive-item,.embed-responsive embed,.embed-responsive iframe,.embed-responsive object,.embed-responsive video{border:0;bottom:0;height:100%;left:0;position:absolute;top:0;width:100%}.embed-responsive-21by9:before{padding-top:42.85714286%}.embed-responsive-16by9:before{padding-top:56.25%}.embed-responsive-4by3:before{padding-top:75%}.embed-responsive-1by1:before{padding-top:100%}.flex-row{flex-direction:row!important}.flex-column{flex-direction:column!important}.flex-row-reverse{flex-direction:row-reverse!important}.flex-column-reverse{flex-direction:column-reverse!important}.flex-wrap{flex-wrap:wrap!important}.flex-nowrap{flex-wrap:nowrap!important}.flex-wrap-reverse{flex-wrap:wrap-reverse!important}.flex-fill{flex:1 1 auto!important}.flex-grow-0{flex-grow:0!important}.flex-grow-1{flex-grow:1!important}.flex-shrink-0{flex-shrink:0!important}.flex-shrink-1{flex-shrink:1!important}.justify-content-start{justify-content:flex-start!important}.justify-content-end{justify-content:flex-end!important}.justify-content-center{justify-content:center!important}.justify-content-between{justify-content:space-between!important}.justify-content-around{justify-content:space-around!important}.align-items-start{align-items:flex-start!important}.align-items-end{align-items:flex-end!important}.align-items-center{align-items:center!important}.align-items-baseline{align-items:baseline!important}.align-items-stretch{align-items:stretch!important}.align-content-start{align-content:flex-start!important}.align-content-end{align-content:flex-end!important}.align-content-center{align-content:center!important}.align-content-between{align-content:space-between!important}.align-content-around{align-content:space-around!important}.align-content-stretch{align-content:stretch!important}.align-self-auto{align-self:auto!important}.align-self-start{align-self:flex-start!important}.align-self-end{align-self:flex-end!important}.align-self-center{align-self:center!important}.align-self-baseline{align-self:baseline!important}.align-self-stretch{align-self:stretch!important}@media (min-width:2px){.flex-sm-row{flex-direction:row!important}.flex-sm-column{flex-direction:column!important}.flex-sm-row-reverse{flex-direction:row-reverse!important}.flex-sm-column-reverse{flex-direction:column-reverse!important}.flex-sm-wrap{flex-wrap:wrap!important}.flex-sm-nowrap{flex-wrap:nowrap!important}.flex-sm-wrap-reverse{flex-wrap:wrap-reverse!important}.flex-sm-fill{flex:1 1 auto!important}.flex-sm-grow-0{flex-grow:0!important}.flex-sm-grow-1{flex-grow:1!important}.flex-sm-shrink-0{flex-shrink:0!important}.flex-sm-shrink-1{flex-shrink:1!important}.justify-content-sm-start{justify-content:flex-start!important}.justify-content-sm-end{justify-content:flex-end!important}.justify-content-sm-center{justify-content:center!important}.justify-content-sm-between{justify-content:space-between!important}.justify-content-sm-around{justify-content:space-around!important}.align-items-sm-start{align-items:flex-start!important}.align-items-sm-end{align-items:flex-end!important}.align-items-sm-center{align-items:center!important}.align-items-sm-baseline{align-items:baseline!important}.align-items-sm-stretch{align-items:stretch!important}.align-content-sm-start{align-content:flex-start!important}.align-content-sm-end{align-content:flex-end!important}.align-content-sm-center{align-content:center!important}.align-content-sm-between{align-content:space-between!important}.align-content-sm-around{align-content:space-around!important}.align-content-sm-stretch{align-content:stretch!important}.align-self-sm-auto{align-self:auto!important}.align-self-sm-start{align-self:flex-start!important}.align-self-sm-end{align-self:flex-end!important}.align-self-sm-center{align-self:center!important}.align-self-sm-baseline{align-self:baseline!important}.align-self-sm-stretch{align-self:stretch!important}}@media (min-width:8px){.flex-md-row{flex-direction:row!important}.flex-md-column{flex-direction:column!important}.flex-md-row-reverse{flex-direction:row-reverse!important}.flex-md-column-reverse{flex-direction:column-reverse!important}.flex-md-wrap{flex-wrap:wrap!important}.flex-md-nowrap{flex-wrap:nowrap!important}.flex-md-wrap-reverse{flex-wrap:wrap-reverse!important}.flex-md-fill{flex:1 1 auto!important}.flex-md-grow-0{flex-grow:0!important}.flex-md-grow-1{flex-grow:1!important}.flex-md-shrink-0{flex-shrink:0!important}.flex-md-shrink-1{flex-shrink:1!important}.justify-content-md-start{justify-content:flex-start!important}.justify-content-md-end{justify-content:flex-end!important}.justify-content-md-center{justify-content:center!important}.justify-content-md-between{justify-content:space-between!important}.justify-content-md-around{justify-content:space-around!important}.align-items-md-start{align-items:flex-start!important}.align-items-md-end{align-items:flex-end!important}.align-items-md-center{align-items:center!important}.align-items-md-baseline{align-items:baseline!important}.align-items-md-stretch{align-items:stretch!important}.align-content-md-start{align-content:flex-start!important}.align-content-md-end{align-content:flex-end!important}.align-content-md-center{align-content:center!important}.align-content-md-between{align-content:space-between!important}.align-content-md-around{align-content:space-around!important}.align-content-md-stretch{align-content:stretch!important}.align-self-md-auto{align-self:auto!important}.align-self-md-start{align-self:flex-start!important}.align-self-md-end{align-self:flex-end!important}.align-self-md-center{align-self:center!important}.align-self-md-baseline{align-self:baseline!important}.align-self-md-stretch{align-self:stretch!important}}@media (min-width:9px){.flex-lg-row{flex-direction:row!important}.flex-lg-column{flex-direction:column!important}.flex-lg-row-reverse{flex-direction:row-reverse!important}.flex-lg-column-reverse{flex-direction:column-reverse!important}.flex-lg-wrap{flex-wrap:wrap!important}.flex-lg-nowrap{flex-wrap:nowrap!important}.flex-lg-wrap-reverse{flex-wrap:wrap-reverse!important}.flex-lg-fill{flex:1 1 auto!important}.flex-lg-grow-0{flex-grow:0!important}.flex-lg-grow-1{flex-grow:1!important}.flex-lg-shrink-0{flex-shrink:0!important}.flex-lg-shrink-1{flex-shrink:1!important}.justify-content-lg-start{justify-content:flex-start!important}.justify-content-lg-end{justify-content:flex-end!important}.justify-content-lg-center{justify-content:center!important}.justify-content-lg-between{justify-content:space-between!important}.justify-content-lg-around{justify-content:space-around!important}.align-items-lg-start{align-items:flex-start!important}.align-items-lg-end{align-items:flex-end!important}.align-items-lg-center{align-items:center!important}.align-items-lg-baseline{align-items:baseline!important}.align-items-lg-stretch{align-items:stretch!important}.align-content-lg-start{align-content:flex-start!important}.align-content-lg-end{align-content:flex-end!important}.align-content-lg-center{align-content:center!important}.align-content-lg-between{align-content:space-between!important}.align-content-lg-around{align-content:space-around!important}.align-content-lg-stretch{align-content:stretch!important}.align-self-lg-auto{align-self:auto!important}.align-self-lg-start{align-self:flex-start!important}.align-self-lg-end{align-self:flex-end!important}.align-self-lg-center{align-self:center!important}.align-self-lg-baseline{align-self:baseline!important}.align-self-lg-stretch{align-self:stretch!important}}@media (min-width:10px){.flex-xl-row{flex-direction:row!important}.flex-xl-column{flex-direction:column!important}.flex-xl-row-reverse{flex-direction:row-reverse!important}.flex-xl-column-reverse{flex-direction:column-reverse!important}.flex-xl-wrap{flex-wrap:wrap!important}.flex-xl-nowrap{flex-wrap:nowrap!important}.flex-xl-wrap-reverse{flex-wrap:wrap-reverse!important}.flex-xl-fill{flex:1 1 auto!important}.flex-xl-grow-0{flex-grow:0!important}.flex-xl-grow-1{flex-grow:1!important}.flex-xl-shrink-0{flex-shrink:0!important}.flex-xl-shrink-1{flex-shrink:1!important}.justify-content-xl-start{justify-content:flex-start!important}.justify-content-xl-end{justify-content:flex-end!important}.justify-content-xl-center{justify-content:center!important}.justify-content-xl-between{justify-content:space-between!important}.justify-content-xl-around{justify-content:space-around!important}.align-items-xl-start{align-items:flex-start!important}.align-items-xl-end{align-items:flex-end!important}.align-items-xl-center{align-items:center!important}.align-items-xl-baseline{align-items:baseline!important}.align-items-xl-stretch{align-items:stretch!important}.align-content-xl-start{align-content:flex-start!important}.align-content-xl-end{align-content:flex-end!important}.align-content-xl-center{align-content:center!important}.align-content-xl-between{align-content:space-between!important}.align-content-xl-around{align-content:space-around!important}.align-content-xl-stretch{align-content:stretch!important}.align-self-xl-auto{align-self:auto!important}.align-self-xl-start{align-self:flex-start!important}.align-self-xl-end{align-self:flex-end!important}.align-self-xl-center{align-self:center!important}.align-self-xl-baseline{align-self:baseline!important}.align-self-xl-stretch{align-self:stretch!important}}.float-left{float:left!important}.float-right{float:right!important}.float-none{float:none!important}@media (min-width:2px){.float-sm-left{float:left!important}.float-sm-right{float:right!important}.float-sm-none{float:none!important}}@media (min-width:8px){.float-md-left{float:left!important}.float-md-right{float:right!important}.float-md-none{float:none!important}}@media (min-width:9px){.float-lg-left{float:left!important}.float-lg-right{float:right!important}.float-lg-none{float:none!important}}@media (min-width:10px){.float-xl-left{float:left!important}.float-xl-right{float:right!important}.float-xl-none{float:none!important}}.user-select-all{-webkit-user-select:all!important;-moz-user-select:all!important;user-select:all!important}.user-select-auto{-webkit-user-select:auto!important;-moz-user-select:auto!important;user-select:auto!important}.user-select-none{-webkit-user-select:none!important;-moz-user-select:none!important;user-select:none!important}.overflow-auto{overflow:auto!important}.overflow-hidden{overflow:hidden!important}.position-static{position:static!important}.position-relative{position:relative!important}.position-absolute{position:absolute!important}.position-fixed{position:fixed!important}.position-sticky{position:sticky!important}.fixed-top{top:0}.fixed-bottom,.fixed-top{left:0;position:fixed;right:0;z-index:1030}.fixed-bottom{bottom:0}@supports (position:sticky){.sticky-top{position:sticky;top:0;z-index:1020}}.sr-only{clip:rect(0,0,0,0);border:0;height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;white-space:nowrap;width:1px}.sr-only-focusable:active,.sr-only-focusable:focus{clip:auto;height:auto;overflow:visible;position:static;white-space:normal;width:auto}.shadow-sm{box-shadow:0 .125rem .25rem rgba(0,0,0,.075)!important}.shadow{box-shadow:0 .5rem 1rem rgba(0,0,0,.15)!important}.shadow-lg{box-shadow:0 1rem 3rem rgba(0,0,0,.175)!important}.shadow-none{box-shadow:none!important}.w-25{width:25%!important}.w-50{width:50%!important}.w-75{width:75%!important}.w-100{width:100%!important}.w-auto{width:auto!important}.h-25{height:25%!important}.h-50{height:50%!important}.h-75{height:75%!important}.h-100{height:100%!important}.h-auto{height:auto!important}.mw-100{max-width:100%!important}.mh-100{max-height:100%!important}.min-vw-100{min-width:100vw!important}.min-vh-100{min-height:100vh!important}.vw-100{width:100vw!important}.vh-100{height:100vh!important}.m-0{margin:0!important}.mt-0,.my-0{margin-top:0!important}.mr-0,.mx-0{margin-right:0!important}.mb-0,.my-0{margin-bottom:0!important}.ml-0,.mx-0{margin-left:0!important}.m-1{margin:.25rem!important}.mt-1,.my-1{margin-top:.25rem!important}.mr-1,.mx-1{margin-right:.25rem!important}.mb-1,.my-1{margin-bottom:.25rem!important}.ml-1,.mx-1{margin-left:.25rem!important}.m-2{margin:.5rem!important}.mt-2,.my-2{margin-top:.5rem!important}.mr-2,.mx-2{margin-right:.5rem!important}.mb-2,.my-2{margin-bottom:.5rem!important}.ml-2,.mx-2{margin-left:.5rem!important}.m-3{margin:1rem!important}.mt-3,.my-3{margin-top:1rem!important}.mr-3,.mx-3{margin-right:1rem!important}.mb-3,.my-3{margin-bottom:1rem!important}.ml-3,.mx-3{margin-left:1rem!important}.m-4{margin:1.5rem!important}.mt-4,.my-4{margin-top:1.5rem!important}.mr-4,.mx-4{margin-right:1.5rem!important}.mb-4,.my-4{margin-bottom:1.5rem!important}.ml-4,.mx-4{margin-left:1.5rem!important}.m-5{margin:3rem!important}.mt-5,.my-5{margin-top:3rem!important}.mr-5,.mx-5{margin-right:3rem!important}.mb-5,.my-5{margin-bottom:3rem!important}.ml-5,.mx-5{margin-left:3rem!important}.p-0{padding:0!important}.pt-0,.py-0{padding-top:0!important}.pr-0,.px-0{padding-right:0!important}.pb-0,.py-0{padding-bottom:0!important}.pl-0,.px-0{padding-left:0!important}.p-1{padding:.25rem!important}.pt-1,.py-1{padding-top:.25rem!important}.pr-1,.px-1{padding-right:.25rem!important}.pb-1,.py-1{padding-bottom:.25rem!important}.pl-1,.px-1{padding-left:.25rem!important}.p-2{padding:.5rem!important}.pt-2,.py-2{padding-top:.5rem!important}.pr-2,.px-2{padding-right:.5rem!important}.pb-2,.py-2{padding-bottom:.5rem!important}.pl-2,.px-2{padding-left:.5rem!important}.p-3{padding:1rem!important}.pt-3,.py-3{padding-top:1rem!important}.pr-3,.px-3{padding-right:1rem!important}.pb-3,.py-3{padding-bottom:1rem!important}.pl-3,.px-3{padding-left:1rem!important}.p-4{padding:1.5rem!important}.pt-4,.py-4{padding-top:1.5rem!important}.pr-4,.px-4{padding-right:1.5rem!important}.pb-4,.py-4{padding-bottom:1.5rem!important}.pl-4,.px-4{padding-left:1.5rem!important}.p-5{padding:3rem!important}.pt-5,.py-5{padding-top:3rem!important}.pr-5,.px-5{padding-right:3rem!important}.pb-5,.py-5{padding-bottom:3rem!important}.pl-5,.px-5{padding-left:3rem!important}.m-n1{margin:-.25rem!important}.mt-n1,.my-n1{margin-top:-.25rem!important}.mr-n1,.mx-n1{margin-right:-.25rem!important}.mb-n1,.my-n1{margin-bottom:-.25rem!important}.ml-n1,.mx-n1{margin-left:-.25rem!important}.m-n2{margin:-.5rem!important}.mt-n2,.my-n2{margin-top:-.5rem!important}.mr-n2,.mx-n2{margin-right:-.5rem!important}.mb-n2,.my-n2{margin-bottom:-.5rem!important}.ml-n2,.mx-n2{margin-left:-.5rem!important}.m-n3{margin:-1rem!important}.mt-n3,.my-n3{margin-top:-1rem!important}.mr-n3,.mx-n3{margin-right:-1rem!important}.mb-n3,.my-n3{margin-bottom:-1rem!important}.ml-n3,.mx-n3{margin-left:-1rem!important}.m-n4{margin:-1.5rem!important}.mt-n4,.my-n4{margin-top:-1.5rem!important}.mr-n4,.mx-n4{margin-right:-1.5rem!important}.mb-n4,.my-n4{margin-bottom:-1.5rem!important}.ml-n4,.mx-n4{margin-left:-1.5rem!important}.m-n5{margin:-3rem!important}.mt-n5,.my-n5{margin-top:-3rem!important}.mr-n5,.mx-n5{margin-right:-3rem!important}.mb-n5,.my-n5{margin-bottom:-3rem!important}.ml-n5,.mx-n5{margin-left:-3rem!important}.m-auto{margin:auto!important}.mt-auto,.my-auto{margin-top:auto!important}.mr-auto,.mx-auto{margin-right:auto!important}.mb-auto,.my-auto{margin-bottom:auto!important}.ml-auto,.mx-auto{margin-left:auto!important}@media (min-width:2px){.m-sm-0{margin:0!important}.mt-sm-0,.my-sm-0{margin-top:0!important}.mr-sm-0,.mx-sm-0{margin-right:0!important}.mb-sm-0,.my-sm-0{margin-bottom:0!important}.ml-sm-0,.mx-sm-0{margin-left:0!important}.m-sm-1{margin:.25rem!important}.mt-sm-1,.my-sm-1{margin-top:.25rem!important}.mr-sm-1,.mx-sm-1{margin-right:.25rem!important}.mb-sm-1,.my-sm-1{margin-bottom:.25rem!important}.ml-sm-1,.mx-sm-1{margin-left:.25rem!important}.m-sm-2{margin:.5rem!important}.mt-sm-2,.my-sm-2{margin-top:.5rem!important}.mr-sm-2,.mx-sm-2{margin-right:.5rem!important}.mb-sm-2,.my-sm-2{margin-bottom:.5rem!important}.ml-sm-2,.mx-sm-2{margin-left:.5rem!important}.m-sm-3{margin:1rem!important}.mt-sm-3,.my-sm-3{margin-top:1rem!important}.mr-sm-3,.mx-sm-3{margin-right:1rem!important}.mb-sm-3,.my-sm-3{margin-bottom:1rem!important}.ml-sm-3,.mx-sm-3{margin-left:1rem!important}.m-sm-4{margin:1.5rem!important}.mt-sm-4,.my-sm-4{margin-top:1.5rem!important}.mr-sm-4,.mx-sm-4{margin-right:1.5rem!important}.mb-sm-4,.my-sm-4{margin-bottom:1.5rem!important}.ml-sm-4,.mx-sm-4{margin-left:1.5rem!important}.m-sm-5{margin:3rem!important}.mt-sm-5,.my-sm-5{margin-top:3rem!important}.mr-sm-5,.mx-sm-5{margin-right:3rem!important}.mb-sm-5,.my-sm-5{margin-bottom:3rem!important}.ml-sm-5,.mx-sm-5{margin-left:3rem!important}.p-sm-0{padding:0!important}.pt-sm-0,.py-sm-0{padding-top:0!important}.pr-sm-0,.px-sm-0{padding-right:0!important}.pb-sm-0,.py-sm-0{padding-bottom:0!important}.pl-sm-0,.px-sm-0{padding-left:0!important}.p-sm-1{padding:.25rem!important}.pt-sm-1,.py-sm-1{padding-top:.25rem!important}.pr-sm-1,.px-sm-1{padding-right:.25rem!important}.pb-sm-1,.py-sm-1{padding-bottom:.25rem!important}.pl-sm-1,.px-sm-1{padding-left:.25rem!important}.p-sm-2{padding:.5rem!important}.pt-sm-2,.py-sm-2{padding-top:.5rem!important}.pr-sm-2,.px-sm-2{padding-right:.5rem!important}.pb-sm-2,.py-sm-2{padding-bottom:.5rem!important}.pl-sm-2,.px-sm-2{padding-left:.5rem!important}.p-sm-3{padding:1rem!important}.pt-sm-3,.py-sm-3{padding-top:1rem!important}.pr-sm-3,.px-sm-3{padding-right:1rem!important}.pb-sm-3,.py-sm-3{padding-bottom:1rem!important}.pl-sm-3,.px-sm-3{padding-left:1rem!important}.p-sm-4{padding:1.5rem!important}.pt-sm-4,.py-sm-4{padding-top:1.5rem!important}.pr-sm-4,.px-sm-4{padding-right:1.5rem!important}.pb-sm-4,.py-sm-4{padding-bottom:1.5rem!important}.pl-sm-4,.px-sm-4{padding-left:1.5rem!important}.p-sm-5{padding:3rem!important}.pt-sm-5,.py-sm-5{padding-top:3rem!important}.pr-sm-5,.px-sm-5{padding-right:3rem!important}.pb-sm-5,.py-sm-5{padding-bottom:3rem!important}.pl-sm-5,.px-sm-5{padding-left:3rem!important}.m-sm-n1{margin:-.25rem!important}.mt-sm-n1,.my-sm-n1{margin-top:-.25rem!important}.mr-sm-n1,.mx-sm-n1{margin-right:-.25rem!important}.mb-sm-n1,.my-sm-n1{margin-bottom:-.25rem!important}.ml-sm-n1,.mx-sm-n1{margin-left:-.25rem!important}.m-sm-n2{margin:-.5rem!important}.mt-sm-n2,.my-sm-n2{margin-top:-.5rem!important}.mr-sm-n2,.mx-sm-n2{margin-right:-.5rem!important}.mb-sm-n2,.my-sm-n2{margin-bottom:-.5rem!important}.ml-sm-n2,.mx-sm-n2{margin-left:-.5rem!important}.m-sm-n3{margin:-1rem!important}.mt-sm-n3,.my-sm-n3{margin-top:-1rem!important}.mr-sm-n3,.mx-sm-n3{margin-right:-1rem!important}.mb-sm-n3,.my-sm-n3{margin-bottom:-1rem!important}.ml-sm-n3,.mx-sm-n3{margin-left:-1rem!important}.m-sm-n4{margin:-1.5rem!important}.mt-sm-n4,.my-sm-n4{margin-top:-1.5rem!important}.mr-sm-n4,.mx-sm-n4{margin-right:-1.5rem!important}.mb-sm-n4,.my-sm-n4{margin-bottom:-1.5rem!important}.ml-sm-n4,.mx-sm-n4{margin-left:-1.5rem!important}.m-sm-n5{margin:-3rem!important}.mt-sm-n5,.my-sm-n5{margin-top:-3rem!important}.mr-sm-n5,.mx-sm-n5{margin-right:-3rem!important}.mb-sm-n5,.my-sm-n5{margin-bottom:-3rem!important}.ml-sm-n5,.mx-sm-n5{margin-left:-3rem!important}.m-sm-auto{margin:auto!important}.mt-sm-auto,.my-sm-auto{margin-top:auto!important}.mr-sm-auto,.mx-sm-auto{margin-right:auto!important}.mb-sm-auto,.my-sm-auto{margin-bottom:auto!important}.ml-sm-auto,.mx-sm-auto{margin-left:auto!important}}@media (min-width:8px){.m-md-0{margin:0!important}.mt-md-0,.my-md-0{margin-top:0!important}.mr-md-0,.mx-md-0{margin-right:0!important}.mb-md-0,.my-md-0{margin-bottom:0!important}.ml-md-0,.mx-md-0{margin-left:0!important}.m-md-1{margin:.25rem!important}.mt-md-1,.my-md-1{margin-top:.25rem!important}.mr-md-1,.mx-md-1{margin-right:.25rem!important}.mb-md-1,.my-md-1{margin-bottom:.25rem!important}.ml-md-1,.mx-md-1{margin-left:.25rem!important}.m-md-2{margin:.5rem!important}.mt-md-2,.my-md-2{margin-top:.5rem!important}.mr-md-2,.mx-md-2{margin-right:.5rem!important}.mb-md-2,.my-md-2{margin-bottom:.5rem!important}.ml-md-2,.mx-md-2{margin-left:.5rem!important}.m-md-3{margin:1rem!important}.mt-md-3,.my-md-3{margin-top:1rem!important}.mr-md-3,.mx-md-3{margin-right:1rem!important}.mb-md-3,.my-md-3{margin-bottom:1rem!important}.ml-md-3,.mx-md-3{margin-left:1rem!important}.m-md-4{margin:1.5rem!important}.mt-md-4,.my-md-4{margin-top:1.5rem!important}.mr-md-4,.mx-md-4{margin-right:1.5rem!important}.mb-md-4,.my-md-4{margin-bottom:1.5rem!important}.ml-md-4,.mx-md-4{margin-left:1.5rem!important}.m-md-5{margin:3rem!important}.mt-md-5,.my-md-5{margin-top:3rem!important}.mr-md-5,.mx-md-5{margin-right:3rem!important}.mb-md-5,.my-md-5{margin-bottom:3rem!important}.ml-md-5,.mx-md-5{margin-left:3rem!important}.p-md-0{padding:0!important}.pt-md-0,.py-md-0{padding-top:0!important}.pr-md-0,.px-md-0{padding-right:0!important}.pb-md-0,.py-md-0{padding-bottom:0!important}.pl-md-0,.px-md-0{padding-left:0!important}.p-md-1{padding:.25rem!important}.pt-md-1,.py-md-1{padding-top:.25rem!important}.pr-md-1,.px-md-1{padding-right:.25rem!important}.pb-md-1,.py-md-1{padding-bottom:.25rem!important}.pl-md-1,.px-md-1{padding-left:.25rem!important}.p-md-2{padding:.5rem!important}.pt-md-2,.py-md-2{padding-top:.5rem!important}.pr-md-2,.px-md-2{padding-right:.5rem!important}.pb-md-2,.py-md-2{padding-bottom:.5rem!important}.pl-md-2,.px-md-2{padding-left:.5rem!important}.p-md-3{padding:1rem!important}.pt-md-3,.py-md-3{padding-top:1rem!important}.pr-md-3,.px-md-3{padding-right:1rem!important}.pb-md-3,.py-md-3{padding-bottom:1rem!important}.pl-md-3,.px-md-3{padding-left:1rem!important}.p-md-4{padding:1.5rem!important}.pt-md-4,.py-md-4{padding-top:1.5rem!important}.pr-md-4,.px-md-4{padding-right:1.5rem!important}.pb-md-4,.py-md-4{padding-bottom:1.5rem!important}.pl-md-4,.px-md-4{padding-left:1.5rem!important}.p-md-5{padding:3rem!important}.pt-md-5,.py-md-5{padding-top:3rem!important}.pr-md-5,.px-md-5{padding-right:3rem!important}.pb-md-5,.py-md-5{padding-bottom:3rem!important}.pl-md-5,.px-md-5{padding-left:3rem!important}.m-md-n1{margin:-.25rem!important}.mt-md-n1,.my-md-n1{margin-top:-.25rem!important}.mr-md-n1,.mx-md-n1{margin-right:-.25rem!important}.mb-md-n1,.my-md-n1{margin-bottom:-.25rem!important}.ml-md-n1,.mx-md-n1{margin-left:-.25rem!important}.m-md-n2{margin:-.5rem!important}.mt-md-n2,.my-md-n2{margin-top:-.5rem!important}.mr-md-n2,.mx-md-n2{margin-right:-.5rem!important}.mb-md-n2,.my-md-n2{margin-bottom:-.5rem!important}.ml-md-n2,.mx-md-n2{margin-left:-.5rem!important}.m-md-n3{margin:-1rem!important}.mt-md-n3,.my-md-n3{margin-top:-1rem!important}.mr-md-n3,.mx-md-n3{margin-right:-1rem!important}.mb-md-n3,.my-md-n3{margin-bottom:-1rem!important}.ml-md-n3,.mx-md-n3{margin-left:-1rem!important}.m-md-n4{margin:-1.5rem!important}.mt-md-n4,.my-md-n4{margin-top:-1.5rem!important}.mr-md-n4,.mx-md-n4{margin-right:-1.5rem!important}.mb-md-n4,.my-md-n4{margin-bottom:-1.5rem!important}.ml-md-n4,.mx-md-n4{margin-left:-1.5rem!important}.m-md-n5{margin:-3rem!important}.mt-md-n5,.my-md-n5{margin-top:-3rem!important}.mr-md-n5,.mx-md-n5{margin-right:-3rem!important}.mb-md-n5,.my-md-n5{margin-bottom:-3rem!important}.ml-md-n5,.mx-md-n5{margin-left:-3rem!important}.m-md-auto{margin:auto!important}.mt-md-auto,.my-md-auto{margin-top:auto!important}.mr-md-auto,.mx-md-auto{margin-right:auto!important}.mb-md-auto,.my-md-auto{margin-bottom:auto!important}.ml-md-auto,.mx-md-auto{margin-left:auto!important}}@media (min-width:9px){.m-lg-0{margin:0!important}.mt-lg-0,.my-lg-0{margin-top:0!important}.mr-lg-0,.mx-lg-0{margin-right:0!important}.mb-lg-0,.my-lg-0{margin-bottom:0!important}.ml-lg-0,.mx-lg-0{margin-left:0!important}.m-lg-1{margin:.25rem!important}.mt-lg-1,.my-lg-1{margin-top:.25rem!important}.mr-lg-1,.mx-lg-1{margin-right:.25rem!important}.mb-lg-1,.my-lg-1{margin-bottom:.25rem!important}.ml-lg-1,.mx-lg-1{margin-left:.25rem!important}.m-lg-2{margin:.5rem!important}.mt-lg-2,.my-lg-2{margin-top:.5rem!important}.mr-lg-2,.mx-lg-2{margin-right:.5rem!important}.mb-lg-2,.my-lg-2{margin-bottom:.5rem!important}.ml-lg-2,.mx-lg-2{margin-left:.5rem!important}.m-lg-3{margin:1rem!important}.mt-lg-3,.my-lg-3{margin-top:1rem!important}.mr-lg-3,.mx-lg-3{margin-right:1rem!important}.mb-lg-3,.my-lg-3{margin-bottom:1rem!important}.ml-lg-3,.mx-lg-3{margin-left:1rem!important}.m-lg-4{margin:1.5rem!important}.mt-lg-4,.my-lg-4{margin-top:1.5rem!important}.mr-lg-4,.mx-lg-4{margin-right:1.5rem!important}.mb-lg-4,.my-lg-4{margin-bottom:1.5rem!important}.ml-lg-4,.mx-lg-4{margin-left:1.5rem!important}.m-lg-5{margin:3rem!important}.mt-lg-5,.my-lg-5{margin-top:3rem!important}.mr-lg-5,.mx-lg-5{margin-right:3rem!important}.mb-lg-5,.my-lg-5{margin-bottom:3rem!important}.ml-lg-5,.mx-lg-5{margin-left:3rem!important}.p-lg-0{padding:0!important}.pt-lg-0,.py-lg-0{padding-top:0!important}.pr-lg-0,.px-lg-0{padding-right:0!important}.pb-lg-0,.py-lg-0{padding-bottom:0!important}.pl-lg-0,.px-lg-0{padding-left:0!important}.p-lg-1{padding:.25rem!important}.pt-lg-1,.py-lg-1{padding-top:.25rem!important}.pr-lg-1,.px-lg-1{padding-right:.25rem!important}.pb-lg-1,.py-lg-1{padding-bottom:.25rem!important}.pl-lg-1,.px-lg-1{padding-left:.25rem!important}.p-lg-2{padding:.5rem!important}.pt-lg-2,.py-lg-2{padding-top:.5rem!important}.pr-lg-2,.px-lg-2{padding-right:.5rem!important}.pb-lg-2,.py-lg-2{padding-bottom:.5rem!important}.pl-lg-2,.px-lg-2{padding-left:.5rem!important}.p-lg-3{padding:1rem!important}.pt-lg-3,.py-lg-3{padding-top:1rem!important}.pr-lg-3,.px-lg-3{padding-right:1rem!important}.pb-lg-3,.py-lg-3{padding-bottom:1rem!important}.pl-lg-3,.px-lg-3{padding-left:1rem!important}.p-lg-4{padding:1.5rem!important}.pt-lg-4,.py-lg-4{padding-top:1.5rem!important}.pr-lg-4,.px-lg-4{padding-right:1.5rem!important}.pb-lg-4,.py-lg-4{padding-bottom:1.5rem!important}.pl-lg-4,.px-lg-4{padding-left:1.5rem!important}.p-lg-5{padding:3rem!important}.pt-lg-5,.py-lg-5{padding-top:3rem!important}.pr-lg-5,.px-lg-5{padding-right:3rem!important}.pb-lg-5,.py-lg-5{padding-bottom:3rem!important}.pl-lg-5,.px-lg-5{padding-left:3rem!important}.m-lg-n1{margin:-.25rem!important}.mt-lg-n1,.my-lg-n1{margin-top:-.25rem!important}.mr-lg-n1,.mx-lg-n1{margin-right:-.25rem!important}.mb-lg-n1,.my-lg-n1{margin-bottom:-.25rem!important}.ml-lg-n1,.mx-lg-n1{margin-left:-.25rem!important}.m-lg-n2{margin:-.5rem!important}.mt-lg-n2,.my-lg-n2{margin-top:-.5rem!important}.mr-lg-n2,.mx-lg-n2{margin-right:-.5rem!important}.mb-lg-n2,.my-lg-n2{margin-bottom:-.5rem!important}.ml-lg-n2,.mx-lg-n2{margin-left:-.5rem!important}.m-lg-n3{margin:-1rem!important}.mt-lg-n3,.my-lg-n3{margin-top:-1rem!important}.mr-lg-n3,.mx-lg-n3{margin-right:-1rem!important}.mb-lg-n3,.my-lg-n3{margin-bottom:-1rem!important}.ml-lg-n3,.mx-lg-n3{margin-left:-1rem!important}.m-lg-n4{margin:-1.5rem!important}.mt-lg-n4,.my-lg-n4{margin-top:-1.5rem!important}.mr-lg-n4,.mx-lg-n4{margin-right:-1.5rem!important}.mb-lg-n4,.my-lg-n4{margin-bottom:-1.5rem!important}.ml-lg-n4,.mx-lg-n4{margin-left:-1.5rem!important}.m-lg-n5{margin:-3rem!important}.mt-lg-n5,.my-lg-n5{margin-top:-3rem!important}.mr-lg-n5,.mx-lg-n5{margin-right:-3rem!important}.mb-lg-n5,.my-lg-n5{margin-bottom:-3rem!important}.ml-lg-n5,.mx-lg-n5{margin-left:-3rem!important}.m-lg-auto{margin:auto!important}.mt-lg-auto,.my-lg-auto{margin-top:auto!important}.mr-lg-auto,.mx-lg-auto{margin-right:auto!important}.mb-lg-auto,.my-lg-auto{margin-bottom:auto!important}.ml-lg-auto,.mx-lg-auto{margin-left:auto!important}}@media (min-width:10px){.m-xl-0{margin:0!important}.mt-xl-0,.my-xl-0{margin-top:0!important}.mr-xl-0,.mx-xl-0{margin-right:0!important}.mb-xl-0,.my-xl-0{margin-bottom:0!important}.ml-xl-0,.mx-xl-0{margin-left:0!important}.m-xl-1{margin:.25rem!important}.mt-xl-1,.my-xl-1{margin-top:.25rem!important}.mr-xl-1,.mx-xl-1{margin-right:.25rem!important}.mb-xl-1,.my-xl-1{margin-bottom:.25rem!important}.ml-xl-1,.mx-xl-1{margin-left:.25rem!important}.m-xl-2{margin:.5rem!important}.mt-xl-2,.my-xl-2{margin-top:.5rem!important}.mr-xl-2,.mx-xl-2{margin-right:.5rem!important}.mb-xl-2,.my-xl-2{margin-bottom:.5rem!important}.ml-xl-2,.mx-xl-2{margin-left:.5rem!important}.m-xl-3{margin:1rem!important}.mt-xl-3,.my-xl-3{margin-top:1rem!important}.mr-xl-3,.mx-xl-3{margin-right:1rem!important}.mb-xl-3,.my-xl-3{margin-bottom:1rem!important}.ml-xl-3,.mx-xl-3{margin-left:1rem!important}.m-xl-4{margin:1.5rem!important}.mt-xl-4,.my-xl-4{margin-top:1.5rem!important}.mr-xl-4,.mx-xl-4{margin-right:1.5rem!important}.mb-xl-4,.my-xl-4{margin-bottom:1.5rem!important}.ml-xl-4,.mx-xl-4{margin-left:1.5rem!important}.m-xl-5{margin:3rem!important}.mt-xl-5,.my-xl-5{margin-top:3rem!important}.mr-xl-5,.mx-xl-5{margin-right:3rem!important}.mb-xl-5,.my-xl-5{margin-bottom:3rem!important}.ml-xl-5,.mx-xl-5{margin-left:3rem!important}.p-xl-0{padding:0!important}.pt-xl-0,.py-xl-0{padding-top:0!important}.pr-xl-0,.px-xl-0{padding-right:0!important}.pb-xl-0,.py-xl-0{padding-bottom:0!important}.pl-xl-0,.px-xl-0{padding-left:0!important}.p-xl-1{padding:.25rem!important}.pt-xl-1,.py-xl-1{padding-top:.25rem!important}.pr-xl-1,.px-xl-1{padding-right:.25rem!important}.pb-xl-1,.py-xl-1{padding-bottom:.25rem!important}.pl-xl-1,.px-xl-1{padding-left:.25rem!important}.p-xl-2{padding:.5rem!important}.pt-xl-2,.py-xl-2{padding-top:.5rem!important}.pr-xl-2,.px-xl-2{padding-right:.5rem!important}.pb-xl-2,.py-xl-2{padding-bottom:.5rem!important}.pl-xl-2,.px-xl-2{padding-left:.5rem!important}.p-xl-3{padding:1rem!important}.pt-xl-3,.py-xl-3{padding-top:1rem!important}.pr-xl-3,.px-xl-3{padding-right:1rem!important}.pb-xl-3,.py-xl-3{padding-bottom:1rem!important}.pl-xl-3,.px-xl-3{padding-left:1rem!important}.p-xl-4{padding:1.5rem!important}.pt-xl-4,.py-xl-4{padding-top:1.5rem!important}.pr-xl-4,.px-xl-4{padding-right:1.5rem!important}.pb-xl-4,.py-xl-4{padding-bottom:1.5rem!important}.pl-xl-4,.px-xl-4{padding-left:1.5rem!important}.p-xl-5{padding:3rem!important}.pt-xl-5,.py-xl-5{padding-top:3rem!important}.pr-xl-5,.px-xl-5{padding-right:3rem!important}.pb-xl-5,.py-xl-5{padding-bottom:3rem!important}.pl-xl-5,.px-xl-5{padding-left:3rem!important}.m-xl-n1{margin:-.25rem!important}.mt-xl-n1,.my-xl-n1{margin-top:-.25rem!important}.mr-xl-n1,.mx-xl-n1{margin-right:-.25rem!important}.mb-xl-n1,.my-xl-n1{margin-bottom:-.25rem!important}.ml-xl-n1,.mx-xl-n1{margin-left:-.25rem!important}.m-xl-n2{margin:-.5rem!important}.mt-xl-n2,.my-xl-n2{margin-top:-.5rem!important}.mr-xl-n2,.mx-xl-n2{margin-right:-.5rem!important}.mb-xl-n2,.my-xl-n2{margin-bottom:-.5rem!important}.ml-xl-n2,.mx-xl-n2{margin-left:-.5rem!important}.m-xl-n3{margin:-1rem!important}.mt-xl-n3,.my-xl-n3{margin-top:-1rem!important}.mr-xl-n3,.mx-xl-n3{margin-right:-1rem!important}.mb-xl-n3,.my-xl-n3{margin-bottom:-1rem!important}.ml-xl-n3,.mx-xl-n3{margin-left:-1rem!important}.m-xl-n4{margin:-1.5rem!important}.mt-xl-n4,.my-xl-n4{margin-top:-1.5rem!important}.mr-xl-n4,.mx-xl-n4{margin-right:-1.5rem!important}.mb-xl-n4,.my-xl-n4{margin-bottom:-1.5rem!important}.ml-xl-n4,.mx-xl-n4{margin-left:-1.5rem!important}.m-xl-n5{margin:-3rem!important}.mt-xl-n5,.my-xl-n5{margin-top:-3rem!important}.mr-xl-n5,.mx-xl-n5{margin-right:-3rem!important}.mb-xl-n5,.my-xl-n5{margin-bottom:-3rem!important}.ml-xl-n5,.mx-xl-n5{margin-left:-3rem!important}.m-xl-auto{margin:auto!important}.mt-xl-auto,.my-xl-auto{margin-top:auto!important}.mr-xl-auto,.mx-xl-auto{margin-right:auto!important}.mb-xl-auto,.my-xl-auto{margin-bottom:auto!important}.ml-xl-auto,.mx-xl-auto{margin-left:auto!important}}.stretched-link:after{background-color:transparent;bottom:0;content:"";left:0;pointer-events:auto;position:absolute;right:0;top:0;z-index:1}.text-monospace{font-family:SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace!important}.text-justify{text-align:justify!important}.text-wrap{white-space:normal!important}.text-nowrap{white-space:nowrap!important}.text-truncate{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.text-left{text-align:left!important}.text-right{text-align:right!important}.text-center{text-align:center!important}@media (min-width:2px){.text-sm-left{text-align:left!important}.text-sm-right{text-align:right!important}.text-sm-center{text-align:center!important}}@media (min-width:8px){.text-md-left{text-align:left!important}.text-md-right{text-align:right!important}.text-md-center{text-align:center!important}}@media (min-width:9px){.text-lg-left{text-align:left!important}.text-lg-right{text-align:right!important}.text-lg-center{text-align:center!important}}@media (min-width:10px){.text-xl-left{text-align:left!important}.text-xl-right{text-align:right!important}.text-xl-center{text-align:center!important}}.text-lowercase{text-transform:lowercase!important}.text-uppercase{text-transform:uppercase!important}.text-capitalize{text-transform:capitalize!important}.font-weight-light{font-weight:300!important}.font-weight-lighter{font-weight:lighter!important}.font-weight-normal{font-weight:400!important}.font-weight-bold{font-weight:700!important}.font-weight-bolder{font-weight:bolder!important}.font-italic{font-style:italic!important}.text-white{color:#fff!important}.text-primary{color:#adadff!important}a.text-primary:focus,a.text-primary:hover{color:#6161ff!important}.text-secondary{color:#494444!important}a.text-secondary:focus,a.text-secondary:hover{color:#211f1f!important}.text-success{color:#1f9d55!important}a.text-success:focus,a.text-success:hover{color:#125d32!important}.text-info{color:#1c3d5a!important}a.text-info:focus,a.text-info:hover{color:#0a1520!important}.text-warning{color:#b08d2f!important}a.text-warning:focus,a.text-warning:hover{color:#745d1f!important}.text-danger{color:#aa2e28!important}a.text-danger:focus,a.text-danger:hover{color:#6c1d19!important}.text-light{color:#f8f9fa!important}a.text-light:focus,a.text-light:hover{color:#cbd3da!important}.text-dark{color:#494444!important}a.text-dark:focus,a.text-dark:hover{color:#211f1f!important}.text-body{color:#e2edf4!important}.text-muted{color:#6c757d!important}.text-black-50{color:rgba(0,0,0,.5)!important}.text-white-50{color:hsla(0,0%,100%,.5)!important}.text-hide{background-color:transparent;border:0;color:transparent;font:0/0 a;text-shadow:none}.text-decoration-none{text-decoration:none!important}.text-break{word-wrap:break-word!important;word-break:break-word!important}.text-reset{color:inherit!important}.visible{visibility:visible!important}.invisible{visibility:hidden!important}@media print{*,:after,:before{box-shadow:none!important;text-shadow:none!important}a:not(.btn){text-decoration:underline}abbr[title]:after{content:" (" attr(title) ")"}pre{white-space:pre-wrap!important}blockquote,pre{border:1px solid #adb5bd}blockquote,img,pre,tr{page-break-inside:avoid}h2,h3,p{orphans:3;widows:3}h2,h3{page-break-after:avoid}@page{size:a3}.container,body{min-width:9px!important}.navbar{display:none}.badge{border:1px solid #000}.table{border-collapse:collapse!important}.table td,.table th{background-color:#fff!important}.table-bordered td,.table-bordered th{border:1px solid #dee2e6!important}.table-dark{color:inherit}.table-dark tbody+tbody,.table-dark td,.table-dark th,.table-dark thead th{border-color:#343434}.table .thead-dark th{border-color:#343434;color:inherit}}body{padding-bottom:20px}.container{width:1140px}html{min-width:1140px}[v-cloak]{display:none}svg.icon{height:1rem;width:1rem}.header{border-bottom:1px solid #343434}.header svg.logo{height:2rem;width:2rem}.sidebar .nav-item a{color:#6e6b6b;padding:.5rem 0}.sidebar .nav-item a svg{fill:#9f9898;height:1rem;margin-right:15px;width:1rem}.sidebar .nav-item a.active{color:#adadff}.sidebar .nav-item a.active svg{fill:#adadff}.card{border:none;box-shadow:0 2px 3px #1c1c1c}.card .bottom-radius{border-bottom-left-radius:.25rem;border-bottom-right-radius:.25rem}.card .card-header{background-color:#120f12;border-bottom:none;padding-bottom:.7rem;padding-top:.7rem}.card .card-header .btn-group .btn{padding:.2rem .5rem}.card .card-header h5{margin:0}.card .table td,.card .table th{padding:.75rem 1.25rem}.card .table.table-sm td,.card .table.table-sm th{padding:1rem 1.25rem}.card .table th{background-color:#181818;border-bottom:0;font-weight:400;padding:.5rem 1.25rem}.card .table:not(.table-borderless) td{border-top:1px solid #343434}.card .table.penultimate-column-right td:nth-last-child(2),.card .table.penultimate-column-right th:nth-last-child(2){text-align:right}.card .table td.table-fit,.card .table th.table-fit{white-space:nowrap;width:1%}.fill-text-color{fill:#e2edf4}.fill-danger{fill:#aa2e28}.fill-warning{fill:#b08d2f}.fill-info{fill:#1c3d5a}.fill-success{fill:#1f9d55}.fill-primary{fill:#adadff}button:hover .fill-primary{fill:#fff}.btn-outline-primary.active .fill-primary{fill:#1c1c1c}.btn-outline-primary:not(:disabled):not(.disabled).active:focus{box-shadow:none!important}.control-action svg{fill:#ccd2df;height:1.2rem;width:1.2rem}.control-action svg:hover{fill:#adadff}.info-icon{fill:#ccd2df}.paginator .btn{color:#9ea7ac;text-decoration:none}.paginator .btn:hover{color:#adadff}@keyframes spin{0%{transform:rotate(0deg)}to{transform:rotate(1turn)}}.spin{animation:spin 2s linear infinite}.card .nav-pills .nav-link.active{background:none;border-bottom:2px solid #adadff;color:#adadff}.card .nav-pills .nav-link{border-radius:0;color:#e2edf4;font-size:.9rem;padding:.75rem 1.25rem}.list-enter-active:not(.dontanimate){transition:background 1s linear}.list-enter:not(.dontanimate),.list-leave-to:not(.dontanimate){background:#505e4a}.card table td{vertical-align:middle!important}.card-bg-secondary,.code-bg{background:#262525}.disabled-watcher{background:#aa2e28;color:#fff;padding:.75rem}.badge-sm{font-size:.75rem} diff --git a/public/vendor/horizon/app.css b/public/vendor/horizon/app.css new file mode 100644 index 00000000..b5224fdf --- /dev/null +++ b/public/vendor/horizon/app.css @@ -0,0 +1,8 @@ +@charset "UTF-8";.vjs-tree{font-family:Monaco,Menlo,Consolas,Bitstream Vera Sans Mono,monospace!important}.vjs-tree.is-root{position:relative}.vjs-tree .vjs-tree__content{padding-left:1em}.vjs-tree .vjs-tree__content.has-line{border-left:1px dotted hsla(0,0%,80%,.28)!important}.vjs-tree .vjs-tree__brackets{cursor:pointer}.vjs-tree .vjs-tree__brackets:hover{color:#20a0ff}.vjs-tree .vjs-value__boolean,.vjs-tree .vjs-value__null,.vjs-tree .vjs-value__number{color:#a291f5!important}.vjs-tree .vjs-value__string{color:#dacb4d!important} + +/*! + * Bootstrap v4.6.2 (https://getbootstrap.com/) + * Copyright 2011-2022 The Bootstrap Authors + * Copyright 2011-2022 Twitter, Inc. + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) + */:root{--blue:#007bff;--indigo:#6610f2;--purple:#6f42c1;--pink:#e83e8c;--red:#dc3545;--orange:#fd7e14;--yellow:#ffc107;--green:#28a745;--teal:#20c997;--cyan:#17a2b8;--white:#fff;--gray:#6c757d;--gray-dark:#343a40;--primary:#7746ec;--secondary:#dae1e7;--success:#51d88a;--info:#bcdefa;--warning:#ffa260;--danger:#ef5753;--light:#f8f9fa;--dark:#343a40;--breakpoint-xs:0;--breakpoint-sm:2px;--breakpoint-md:8px;--breakpoint-lg:9px;--breakpoint-xl:10px;--font-family-sans-serif:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,"Noto Sans","Liberation Sans",sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";--font-family-monospace:SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace}*,:after,:before{box-sizing:border-box}html{-webkit-text-size-adjust:100%;-webkit-tap-highlight-color:rgba(0,0,0,0);font-family:sans-serif;line-height:1.15}article,aside,figcaption,figure,footer,header,hgroup,main,nav,section{display:block}body{background-color:#ebebeb;color:#212529;font-family:Nunito,sans-serif;font-size:.95rem;font-weight:400;line-height:1.5;margin:0;text-align:left}[tabindex="-1"]:focus:not(:focus-visible){outline:0!important}hr{box-sizing:content-box;height:0;overflow:visible}h1,h2,h3,h4,h5,h6{margin-bottom:.5rem;margin-top:0}p{margin-bottom:1rem;margin-top:0}abbr[data-original-title],abbr[title]{border-bottom:0;cursor:help;text-decoration:underline;-webkit-text-decoration:underline dotted;text-decoration:underline dotted;-webkit-text-decoration-skip-ink:none;text-decoration-skip-ink:none}address{font-style:normal;line-height:inherit}address,dl,ol,ul{margin-bottom:1rem}dl,ol,ul{margin-top:0}ol ol,ol ul,ul ol,ul ul{margin-bottom:0}dt{font-weight:700}dd{margin-bottom:.5rem;margin-left:0}blockquote{margin:0 0 1rem}b,strong{font-weight:bolder}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}a{background-color:transparent;color:#7746ec;text-decoration:none}a:hover{color:#4d15d0;text-decoration:underline}a:not([href]):not([class]),a:not([href]):not([class]):hover{color:inherit;text-decoration:none}code,kbd,pre,samp{font-family:SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-size:1em}pre{-ms-overflow-style:scrollbar;margin-bottom:1rem;margin-top:0;overflow:auto}figure{margin:0 0 1rem}img{border-style:none}img,svg{vertical-align:middle}svg{overflow:hidden}table{border-collapse:collapse}caption{caption-side:bottom;color:#6c757d;padding-bottom:.75rem;padding-top:.75rem;text-align:left}th{text-align:inherit;text-align:-webkit-match-parent}label{display:inline-block;margin-bottom:.5rem}button{border-radius:0}button:focus:not(:focus-visible){outline:0}button,input,optgroup,select,textarea{font-family:inherit;font-size:inherit;line-height:inherit;margin:0}button,input{overflow:visible}button,select{text-transform:none}[role=button]{cursor:pointer}select{word-wrap:normal}[type=button],[type=reset],[type=submit],button{-webkit-appearance:button}[type=button]:not(:disabled),[type=reset]:not(:disabled),[type=submit]:not(:disabled),button:not(:disabled){cursor:pointer}[type=button]::-moz-focus-inner,[type=reset]::-moz-focus-inner,[type=submit]::-moz-focus-inner,button::-moz-focus-inner{border-style:none;padding:0}input[type=checkbox],input[type=radio]{box-sizing:border-box;padding:0}textarea{overflow:auto;resize:vertical}fieldset{border:0;margin:0;min-width:0;padding:0}legend{color:inherit;display:block;font-size:1.5rem;line-height:inherit;margin-bottom:.5rem;max-width:100%;padding:0;white-space:normal;width:100%}progress{vertical-align:baseline}[type=number]::-webkit-inner-spin-button,[type=number]::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:none;outline-offset:-2px}[type=search]::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}output{display:inline-block}summary{cursor:pointer;display:list-item}template{display:none}[hidden]{display:none!important}.h1,.h2,.h3,.h4,.h5,.h6,h1,h2,h3,h4,h5,h6{font-weight:500;line-height:1.2;margin-bottom:.5rem}.h1,h1{font-size:2.375rem}.h2,h2{font-size:1.9rem}.h3,h3{font-size:1.6625rem}.h4,h4{font-size:1.425rem}.h5,h5{font-size:1.1875rem}.h6,h6{font-size:.95rem}.lead{font-size:1.1875rem;font-weight:300}.display-1{font-size:6rem}.display-1,.display-2{font-weight:300;line-height:1.2}.display-2{font-size:5.5rem}.display-3{font-size:4.5rem}.display-3,.display-4{font-weight:300;line-height:1.2}.display-4{font-size:3.5rem}hr{border:0;border-top:1px solid rgba(0,0,0,.1);margin-bottom:1rem;margin-top:1rem}.small,small{font-size:.875em;font-weight:400}.mark,mark{background-color:#fcf8e3;padding:.2em}.list-inline,.list-unstyled{list-style:none;padding-left:0}.list-inline-item{display:inline-block}.list-inline-item:not(:last-child){margin-right:.5rem}.initialism{font-size:90%;text-transform:uppercase}.blockquote{font-size:1.1875rem;margin-bottom:1rem}.blockquote-footer{color:#6c757d;display:block;font-size:.875em}.blockquote-footer:before{content:"— "}.img-fluid,.img-thumbnail{height:auto;max-width:100%}.img-thumbnail{background-color:#ebebeb;border:1px solid #dee2e6;border-radius:.25rem;padding:.25rem}.figure{display:inline-block}.figure-img{line-height:1;margin-bottom:.5rem}.figure-caption{color:#6c757d;font-size:90%}code{word-wrap:break-word;color:#e83e8c;font-size:87.5%}a>code{color:inherit}kbd{background-color:#212529;border-radius:.2rem;color:#fff;font-size:87.5%;padding:.2rem .4rem}kbd kbd{font-size:100%;font-weight:700;padding:0}pre{color:#212529;display:block;font-size:87.5%}pre code{color:inherit;font-size:inherit;word-break:normal}.pre-scrollable{max-height:340px;overflow-y:scroll}.container,.container-fluid,.container-lg,.container-md,.container-sm,.container-xl{margin-left:auto;margin-right:auto;padding-left:15px;padding-right:15px;width:100%}@media (min-width:2px){.container,.container-sm{max-width:1137px}}@media (min-width:8px){.container,.container-md,.container-sm{max-width:1138px}}@media (min-width:9px){.container,.container-lg,.container-md,.container-sm{max-width:1139px}}@media (min-width:10px){.container,.container-lg,.container-md,.container-sm,.container-xl{max-width:1140px}}.row{display:flex;flex-wrap:wrap;margin-left:-15px;margin-right:-15px}.no-gutters{margin-left:0;margin-right:0}.no-gutters>.col,.no-gutters>[class*=col-]{padding-left:0;padding-right:0}.col,.col-1,.col-10,.col-11,.col-12,.col-2,.col-3,.col-4,.col-5,.col-6,.col-7,.col-8,.col-9,.col-auto,.col-lg,.col-lg-1,.col-lg-10,.col-lg-11,.col-lg-12,.col-lg-2,.col-lg-3,.col-lg-4,.col-lg-5,.col-lg-6,.col-lg-7,.col-lg-8,.col-lg-9,.col-lg-auto,.col-md,.col-md-1,.col-md-10,.col-md-11,.col-md-12,.col-md-2,.col-md-3,.col-md-4,.col-md-5,.col-md-6,.col-md-7,.col-md-8,.col-md-9,.col-md-auto,.col-sm,.col-sm-1,.col-sm-10,.col-sm-11,.col-sm-12,.col-sm-2,.col-sm-3,.col-sm-4,.col-sm-5,.col-sm-6,.col-sm-7,.col-sm-8,.col-sm-9,.col-sm-auto,.col-xl,.col-xl-1,.col-xl-10,.col-xl-11,.col-xl-12,.col-xl-2,.col-xl-3,.col-xl-4,.col-xl-5,.col-xl-6,.col-xl-7,.col-xl-8,.col-xl-9,.col-xl-auto{padding-left:15px;padding-right:15px;position:relative;width:100%}.col{flex-basis:0;flex-grow:1;max-width:100%}.row-cols-1>*{flex:0 0 100%;max-width:100%}.row-cols-2>*{flex:0 0 50%;max-width:50%}.row-cols-3>*{flex:0 0 33.3333333333%;max-width:33.3333333333%}.row-cols-4>*{flex:0 0 25%;max-width:25%}.row-cols-5>*{flex:0 0 20%;max-width:20%}.row-cols-6>*{flex:0 0 16.6666666667%;max-width:16.6666666667%}.col-auto{flex:0 0 auto;max-width:100%;width:auto}.col-1{flex:0 0 8.33333333%;max-width:8.33333333%}.col-2{flex:0 0 16.66666667%;max-width:16.66666667%}.col-3{flex:0 0 25%;max-width:25%}.col-4{flex:0 0 33.33333333%;max-width:33.33333333%}.col-5{flex:0 0 41.66666667%;max-width:41.66666667%}.col-6{flex:0 0 50%;max-width:50%}.col-7{flex:0 0 58.33333333%;max-width:58.33333333%}.col-8{flex:0 0 66.66666667%;max-width:66.66666667%}.col-9{flex:0 0 75%;max-width:75%}.col-10{flex:0 0 83.33333333%;max-width:83.33333333%}.col-11{flex:0 0 91.66666667%;max-width:91.66666667%}.col-12{flex:0 0 100%;max-width:100%}.order-first{order:-1}.order-last{order:13}.order-0{order:0}.order-1{order:1}.order-2{order:2}.order-3{order:3}.order-4{order:4}.order-5{order:5}.order-6{order:6}.order-7{order:7}.order-8{order:8}.order-9{order:9}.order-10{order:10}.order-11{order:11}.order-12{order:12}.offset-1{margin-left:8.33333333%}.offset-2{margin-left:16.66666667%}.offset-3{margin-left:25%}.offset-4{margin-left:33.33333333%}.offset-5{margin-left:41.66666667%}.offset-6{margin-left:50%}.offset-7{margin-left:58.33333333%}.offset-8{margin-left:66.66666667%}.offset-9{margin-left:75%}.offset-10{margin-left:83.33333333%}.offset-11{margin-left:91.66666667%}@media (min-width:2px){.col-sm{flex-basis:0;flex-grow:1;max-width:100%}.row-cols-sm-1>*{flex:0 0 100%;max-width:100%}.row-cols-sm-2>*{flex:0 0 50%;max-width:50%}.row-cols-sm-3>*{flex:0 0 33.3333333333%;max-width:33.3333333333%}.row-cols-sm-4>*{flex:0 0 25%;max-width:25%}.row-cols-sm-5>*{flex:0 0 20%;max-width:20%}.row-cols-sm-6>*{flex:0 0 16.6666666667%;max-width:16.6666666667%}.col-sm-auto{flex:0 0 auto;max-width:100%;width:auto}.col-sm-1{flex:0 0 8.33333333%;max-width:8.33333333%}.col-sm-2{flex:0 0 16.66666667%;max-width:16.66666667%}.col-sm-3{flex:0 0 25%;max-width:25%}.col-sm-4{flex:0 0 33.33333333%;max-width:33.33333333%}.col-sm-5{flex:0 0 41.66666667%;max-width:41.66666667%}.col-sm-6{flex:0 0 50%;max-width:50%}.col-sm-7{flex:0 0 58.33333333%;max-width:58.33333333%}.col-sm-8{flex:0 0 66.66666667%;max-width:66.66666667%}.col-sm-9{flex:0 0 75%;max-width:75%}.col-sm-10{flex:0 0 83.33333333%;max-width:83.33333333%}.col-sm-11{flex:0 0 91.66666667%;max-width:91.66666667%}.col-sm-12{flex:0 0 100%;max-width:100%}.order-sm-first{order:-1}.order-sm-last{order:13}.order-sm-0{order:0}.order-sm-1{order:1}.order-sm-2{order:2}.order-sm-3{order:3}.order-sm-4{order:4}.order-sm-5{order:5}.order-sm-6{order:6}.order-sm-7{order:7}.order-sm-8{order:8}.order-sm-9{order:9}.order-sm-10{order:10}.order-sm-11{order:11}.order-sm-12{order:12}.offset-sm-0{margin-left:0}.offset-sm-1{margin-left:8.33333333%}.offset-sm-2{margin-left:16.66666667%}.offset-sm-3{margin-left:25%}.offset-sm-4{margin-left:33.33333333%}.offset-sm-5{margin-left:41.66666667%}.offset-sm-6{margin-left:50%}.offset-sm-7{margin-left:58.33333333%}.offset-sm-8{margin-left:66.66666667%}.offset-sm-9{margin-left:75%}.offset-sm-10{margin-left:83.33333333%}.offset-sm-11{margin-left:91.66666667%}}@media (min-width:8px){.col-md{flex-basis:0;flex-grow:1;max-width:100%}.row-cols-md-1>*{flex:0 0 100%;max-width:100%}.row-cols-md-2>*{flex:0 0 50%;max-width:50%}.row-cols-md-3>*{flex:0 0 33.3333333333%;max-width:33.3333333333%}.row-cols-md-4>*{flex:0 0 25%;max-width:25%}.row-cols-md-5>*{flex:0 0 20%;max-width:20%}.row-cols-md-6>*{flex:0 0 16.6666666667%;max-width:16.6666666667%}.col-md-auto{flex:0 0 auto;max-width:100%;width:auto}.col-md-1{flex:0 0 8.33333333%;max-width:8.33333333%}.col-md-2{flex:0 0 16.66666667%;max-width:16.66666667%}.col-md-3{flex:0 0 25%;max-width:25%}.col-md-4{flex:0 0 33.33333333%;max-width:33.33333333%}.col-md-5{flex:0 0 41.66666667%;max-width:41.66666667%}.col-md-6{flex:0 0 50%;max-width:50%}.col-md-7{flex:0 0 58.33333333%;max-width:58.33333333%}.col-md-8{flex:0 0 66.66666667%;max-width:66.66666667%}.col-md-9{flex:0 0 75%;max-width:75%}.col-md-10{flex:0 0 83.33333333%;max-width:83.33333333%}.col-md-11{flex:0 0 91.66666667%;max-width:91.66666667%}.col-md-12{flex:0 0 100%;max-width:100%}.order-md-first{order:-1}.order-md-last{order:13}.order-md-0{order:0}.order-md-1{order:1}.order-md-2{order:2}.order-md-3{order:3}.order-md-4{order:4}.order-md-5{order:5}.order-md-6{order:6}.order-md-7{order:7}.order-md-8{order:8}.order-md-9{order:9}.order-md-10{order:10}.order-md-11{order:11}.order-md-12{order:12}.offset-md-0{margin-left:0}.offset-md-1{margin-left:8.33333333%}.offset-md-2{margin-left:16.66666667%}.offset-md-3{margin-left:25%}.offset-md-4{margin-left:33.33333333%}.offset-md-5{margin-left:41.66666667%}.offset-md-6{margin-left:50%}.offset-md-7{margin-left:58.33333333%}.offset-md-8{margin-left:66.66666667%}.offset-md-9{margin-left:75%}.offset-md-10{margin-left:83.33333333%}.offset-md-11{margin-left:91.66666667%}}@media (min-width:9px){.col-lg{flex-basis:0;flex-grow:1;max-width:100%}.row-cols-lg-1>*{flex:0 0 100%;max-width:100%}.row-cols-lg-2>*{flex:0 0 50%;max-width:50%}.row-cols-lg-3>*{flex:0 0 33.3333333333%;max-width:33.3333333333%}.row-cols-lg-4>*{flex:0 0 25%;max-width:25%}.row-cols-lg-5>*{flex:0 0 20%;max-width:20%}.row-cols-lg-6>*{flex:0 0 16.6666666667%;max-width:16.6666666667%}.col-lg-auto{flex:0 0 auto;max-width:100%;width:auto}.col-lg-1{flex:0 0 8.33333333%;max-width:8.33333333%}.col-lg-2{flex:0 0 16.66666667%;max-width:16.66666667%}.col-lg-3{flex:0 0 25%;max-width:25%}.col-lg-4{flex:0 0 33.33333333%;max-width:33.33333333%}.col-lg-5{flex:0 0 41.66666667%;max-width:41.66666667%}.col-lg-6{flex:0 0 50%;max-width:50%}.col-lg-7{flex:0 0 58.33333333%;max-width:58.33333333%}.col-lg-8{flex:0 0 66.66666667%;max-width:66.66666667%}.col-lg-9{flex:0 0 75%;max-width:75%}.col-lg-10{flex:0 0 83.33333333%;max-width:83.33333333%}.col-lg-11{flex:0 0 91.66666667%;max-width:91.66666667%}.col-lg-12{flex:0 0 100%;max-width:100%}.order-lg-first{order:-1}.order-lg-last{order:13}.order-lg-0{order:0}.order-lg-1{order:1}.order-lg-2{order:2}.order-lg-3{order:3}.order-lg-4{order:4}.order-lg-5{order:5}.order-lg-6{order:6}.order-lg-7{order:7}.order-lg-8{order:8}.order-lg-9{order:9}.order-lg-10{order:10}.order-lg-11{order:11}.order-lg-12{order:12}.offset-lg-0{margin-left:0}.offset-lg-1{margin-left:8.33333333%}.offset-lg-2{margin-left:16.66666667%}.offset-lg-3{margin-left:25%}.offset-lg-4{margin-left:33.33333333%}.offset-lg-5{margin-left:41.66666667%}.offset-lg-6{margin-left:50%}.offset-lg-7{margin-left:58.33333333%}.offset-lg-8{margin-left:66.66666667%}.offset-lg-9{margin-left:75%}.offset-lg-10{margin-left:83.33333333%}.offset-lg-11{margin-left:91.66666667%}}@media (min-width:10px){.col-xl{flex-basis:0;flex-grow:1;max-width:100%}.row-cols-xl-1>*{flex:0 0 100%;max-width:100%}.row-cols-xl-2>*{flex:0 0 50%;max-width:50%}.row-cols-xl-3>*{flex:0 0 33.3333333333%;max-width:33.3333333333%}.row-cols-xl-4>*{flex:0 0 25%;max-width:25%}.row-cols-xl-5>*{flex:0 0 20%;max-width:20%}.row-cols-xl-6>*{flex:0 0 16.6666666667%;max-width:16.6666666667%}.col-xl-auto{flex:0 0 auto;max-width:100%;width:auto}.col-xl-1{flex:0 0 8.33333333%;max-width:8.33333333%}.col-xl-2{flex:0 0 16.66666667%;max-width:16.66666667%}.col-xl-3{flex:0 0 25%;max-width:25%}.col-xl-4{flex:0 0 33.33333333%;max-width:33.33333333%}.col-xl-5{flex:0 0 41.66666667%;max-width:41.66666667%}.col-xl-6{flex:0 0 50%;max-width:50%}.col-xl-7{flex:0 0 58.33333333%;max-width:58.33333333%}.col-xl-8{flex:0 0 66.66666667%;max-width:66.66666667%}.col-xl-9{flex:0 0 75%;max-width:75%}.col-xl-10{flex:0 0 83.33333333%;max-width:83.33333333%}.col-xl-11{flex:0 0 91.66666667%;max-width:91.66666667%}.col-xl-12{flex:0 0 100%;max-width:100%}.order-xl-first{order:-1}.order-xl-last{order:13}.order-xl-0{order:0}.order-xl-1{order:1}.order-xl-2{order:2}.order-xl-3{order:3}.order-xl-4{order:4}.order-xl-5{order:5}.order-xl-6{order:6}.order-xl-7{order:7}.order-xl-8{order:8}.order-xl-9{order:9}.order-xl-10{order:10}.order-xl-11{order:11}.order-xl-12{order:12}.offset-xl-0{margin-left:0}.offset-xl-1{margin-left:8.33333333%}.offset-xl-2{margin-left:16.66666667%}.offset-xl-3{margin-left:25%}.offset-xl-4{margin-left:33.33333333%}.offset-xl-5{margin-left:41.66666667%}.offset-xl-6{margin-left:50%}.offset-xl-7{margin-left:58.33333333%}.offset-xl-8{margin-left:66.66666667%}.offset-xl-9{margin-left:75%}.offset-xl-10{margin-left:83.33333333%}.offset-xl-11{margin-left:91.66666667%}}.table{color:#212529;margin-bottom:1rem;width:100%}.table td,.table th{border-top:1px solid #efefef;padding:.75rem;vertical-align:top}.table thead th{border-bottom:2px solid #efefef;vertical-align:bottom}.table tbody+tbody{border-top:2px solid #efefef}.table-sm td,.table-sm th{padding:.3rem}.table-bordered,.table-bordered td,.table-bordered th{border:1px solid #efefef}.table-bordered thead td,.table-bordered thead th{border-bottom-width:2px}.table-borderless tbody+tbody,.table-borderless td,.table-borderless th,.table-borderless thead th{border:0}.table-striped tbody tr:nth-of-type(odd){background-color:rgba(0,0,0,.05)}.table-hover tbody tr:hover{background-color:#f1f7fa;color:#212529}.table-primary,.table-primary>td,.table-primary>th{background-color:#d9cbfa}.table-primary tbody+tbody,.table-primary td,.table-primary th,.table-primary thead th{border-color:#b89ff5}.table-hover .table-primary:hover,.table-hover .table-primary:hover>td,.table-hover .table-primary:hover>th{background-color:#c8b4f8}.table-secondary,.table-secondary>td,.table-secondary>th{background-color:#f5f7f8}.table-secondary tbody+tbody,.table-secondary td,.table-secondary th,.table-secondary thead th{border-color:#eceff3}.table-hover .table-secondary:hover,.table-hover .table-secondary:hover>td,.table-hover .table-secondary:hover>th{background-color:#e6ebee}.table-success,.table-success>td,.table-success>th{background-color:#cef4de}.table-success tbody+tbody,.table-success td,.table-success th,.table-success thead th{border-color:#a5ebc2}.table-hover .table-success:hover,.table-hover .table-success:hover>td,.table-hover .table-success:hover>th{background-color:#b9efd0}.table-info,.table-info>td,.table-info>th{background-color:#ecf6fe}.table-info tbody+tbody,.table-info td,.table-info th,.table-info thead th{border-color:#dceefc}.table-hover .table-info:hover,.table-hover .table-info:hover>td,.table-hover .table-info:hover>th{background-color:#d4ebfd}.table-warning,.table-warning>td,.table-warning>th{background-color:#ffe5d2}.table-warning tbody+tbody,.table-warning td,.table-warning th,.table-warning thead th{border-color:#ffcfac}.table-hover .table-warning:hover,.table-hover .table-warning:hover>td,.table-hover .table-warning:hover>th{background-color:#ffd6b9}.table-danger,.table-danger>td,.table-danger>th{background-color:#fbd0cf}.table-danger tbody+tbody,.table-danger td,.table-danger th,.table-danger thead th{border-color:#f7a8a6}.table-hover .table-danger:hover,.table-hover .table-danger:hover>td,.table-hover .table-danger:hover>th{background-color:#f9b9b7}.table-light,.table-light>td,.table-light>th{background-color:#fdfdfe}.table-light tbody+tbody,.table-light td,.table-light th,.table-light thead th{border-color:#fbfcfc}.table-hover .table-light:hover,.table-hover .table-light:hover>td,.table-hover .table-light:hover>th{background-color:#ececf6}.table-dark,.table-dark>td,.table-dark>th{background-color:#c6c8ca}.table-dark tbody+tbody,.table-dark td,.table-dark th,.table-dark thead th{border-color:#95999c}.table-hover .table-dark:hover,.table-hover .table-dark:hover>td,.table-hover .table-dark:hover>th{background-color:#b9bbbe}.table-active,.table-active>td,.table-active>th{background-color:#f1f7fa}.table-hover .table-active:hover,.table-hover .table-active:hover>td,.table-hover .table-active:hover>th{background-color:#deecf3}.table .thead-dark th{background-color:#343a40;border-color:#454d55;color:#fff}.table .thead-light th{background-color:#e9ecef;border-color:#efefef;color:#495057}.table-dark{background-color:#343a40;color:#fff}.table-dark td,.table-dark th,.table-dark thead th{border-color:#454d55}.table-dark.table-bordered{border:0}.table-dark.table-striped tbody tr:nth-of-type(odd){background-color:hsla(0,0%,100%,.05)}.table-dark.table-hover tbody tr:hover{background-color:hsla(0,0%,100%,.075);color:#fff}@media (max-width:1.98px){.table-responsive-sm{-webkit-overflow-scrolling:touch;display:block;overflow-x:auto;width:100%}.table-responsive-sm>.table-bordered{border:0}}@media (max-width:7.98px){.table-responsive-md{-webkit-overflow-scrolling:touch;display:block;overflow-x:auto;width:100%}.table-responsive-md>.table-bordered{border:0}}@media (max-width:8.98px){.table-responsive-lg{-webkit-overflow-scrolling:touch;display:block;overflow-x:auto;width:100%}.table-responsive-lg>.table-bordered{border:0}}@media (max-width:9.98px){.table-responsive-xl{-webkit-overflow-scrolling:touch;display:block;overflow-x:auto;width:100%}.table-responsive-xl>.table-bordered{border:0}}.table-responsive{-webkit-overflow-scrolling:touch;display:block;overflow-x:auto;width:100%}.table-responsive>.table-bordered{border:0}.form-control{background-clip:padding-box;background-color:#fff;border:1px solid #ced4da;border-radius:.25rem;color:#495057;display:block;font-size:.95rem;font-weight:400;height:calc(1.5em + .75rem + 2px);line-height:1.5;padding:.375rem .75rem;transition:border-color .15s ease-in-out,box-shadow .15s ease-in-out;width:100%}@media (prefers-reduced-motion:reduce){.form-control{transition:none}}.form-control::-ms-expand{background-color:transparent;border:0}.form-control:focus{background-color:#fff;border-color:#ccbaf8;box-shadow:0 0 0 .2rem rgba(119,70,236,.25);color:#495057;outline:0}.form-control::-moz-placeholder{color:#6c757d;opacity:1}.form-control::placeholder{color:#6c757d;opacity:1}.form-control:disabled,.form-control[readonly]{background-color:#e9ecef;opacity:1}input[type=date].form-control,input[type=datetime-local].form-control,input[type=month].form-control,input[type=time].form-control{-webkit-appearance:none;-moz-appearance:none;appearance:none}select.form-control:-moz-focusring{color:transparent;text-shadow:0 0 0 #495057}select.form-control:focus::-ms-value{background-color:#fff;color:#495057}.form-control-file,.form-control-range{display:block;width:100%}.col-form-label{font-size:inherit;line-height:1.5;margin-bottom:0;padding-bottom:calc(.375rem + 1px);padding-top:calc(.375rem + 1px)}.col-form-label-lg{font-size:1.1875rem;line-height:1.5;padding-bottom:calc(.5rem + 1px);padding-top:calc(.5rem + 1px)}.col-form-label-sm{font-size:.83125rem;line-height:1.5;padding-bottom:calc(.25rem + 1px);padding-top:calc(.25rem + 1px)}.form-control-plaintext{background-color:transparent;border:solid transparent;border-width:1px 0;color:#212529;display:block;font-size:.95rem;line-height:1.5;margin-bottom:0;padding:.375rem 0;width:100%}.form-control-plaintext.form-control-lg,.form-control-plaintext.form-control-sm{padding-left:0;padding-right:0}.form-control-sm{border-radius:.2rem;font-size:.83125rem;height:calc(1.5em + .5rem + 2px);line-height:1.5;padding:.25rem .5rem}.form-control-lg{border-radius:.3rem;font-size:1.1875rem;height:calc(1.5em + 1rem + 2px);line-height:1.5;padding:.5rem 1rem}select.form-control[multiple],select.form-control[size],textarea.form-control{height:auto}.form-group{margin-bottom:1rem}.form-text{display:block;margin-top:.25rem}.form-row{display:flex;flex-wrap:wrap;margin-left:-5px;margin-right:-5px}.form-row>.col,.form-row>[class*=col-]{padding-left:5px;padding-right:5px}.form-check{display:block;padding-left:1.25rem;position:relative}.form-check-input{margin-left:-1.25rem;margin-top:.3rem;position:absolute}.form-check-input:disabled~.form-check-label,.form-check-input[disabled]~.form-check-label{color:#6c757d}.form-check-label{margin-bottom:0}.form-check-inline{align-items:center;display:inline-flex;margin-right:.75rem;padding-left:0}.form-check-inline .form-check-input{margin-left:0;margin-right:.3125rem;margin-top:0;position:static}.valid-feedback{color:#51d88a;display:none;font-size:.875em;margin-top:.25rem;width:100%}.valid-tooltip{background-color:rgba(81,216,138,.9);border-radius:.25rem;color:#212529;display:none;font-size:.83125rem;left:0;line-height:1.5;margin-top:.1rem;max-width:100%;padding:.25rem .5rem;position:absolute;top:100%;z-index:5}.form-row>.col>.valid-tooltip,.form-row>[class*=col-]>.valid-tooltip{left:5px}.is-valid~.valid-feedback,.is-valid~.valid-tooltip,.was-validated :valid~.valid-feedback,.was-validated :valid~.valid-tooltip{display:block}.form-control.is-valid,.was-validated .form-control:valid{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='8' height='8'%3E%3Cpath fill='%2351d88a' d='M2.3 6.73.6 4.53c-.4-1.04.46-1.4 1.1-.8l1.1 1.4 3.4-3.8c.6-.63 1.6-.27 1.2.7l-4 4.6c-.43.5-.8.4-1.1.1z'/%3E%3C/svg%3E");background-position:right calc(.375em + .1875rem) center;background-repeat:no-repeat;background-size:calc(.75em + .375rem) calc(.75em + .375rem);border-color:#51d88a;padding-right:calc(1.5em + .75rem)!important}.form-control.is-valid:focus,.was-validated .form-control:valid:focus{border-color:#51d88a;box-shadow:0 0 0 .2rem rgba(81,216,138,.25)}.was-validated select.form-control:valid,select.form-control.is-valid{background-position:right 1.5rem center;padding-right:3rem!important}.was-validated textarea.form-control:valid,textarea.form-control.is-valid{background-position:top calc(.375em + .1875rem) right calc(.375em + .1875rem);padding-right:calc(1.5em + .75rem)}.custom-select.is-valid,.was-validated .custom-select:valid{background:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='4' height='5'%3E%3Cpath fill='%23343a40' d='M2 0 0 2h4zm0 5L0 3h4z'/%3E%3C/svg%3E") right .75rem center/8px 10px no-repeat,#fff url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='8' height='8'%3E%3Cpath fill='%2351d88a' d='M2.3 6.73.6 4.53c-.4-1.04.46-1.4 1.1-.8l1.1 1.4 3.4-3.8c.6-.63 1.6-.27 1.2.7l-4 4.6c-.43.5-.8.4-1.1.1z'/%3E%3C/svg%3E") center right 1.75rem/calc(.75em + .375rem) calc(.75em + .375rem) no-repeat;border-color:#51d88a;padding-right:calc(.75em + 2.3125rem)!important}.custom-select.is-valid:focus,.was-validated .custom-select:valid:focus{border-color:#51d88a;box-shadow:0 0 0 .2rem rgba(81,216,138,.25)}.form-check-input.is-valid~.form-check-label,.was-validated .form-check-input:valid~.form-check-label{color:#51d88a}.form-check-input.is-valid~.valid-feedback,.form-check-input.is-valid~.valid-tooltip,.was-validated .form-check-input:valid~.valid-feedback,.was-validated .form-check-input:valid~.valid-tooltip{display:block}.custom-control-input.is-valid~.custom-control-label,.was-validated .custom-control-input:valid~.custom-control-label{color:#51d88a}.custom-control-input.is-valid~.custom-control-label:before,.was-validated .custom-control-input:valid~.custom-control-label:before{border-color:#51d88a}.custom-control-input.is-valid:checked~.custom-control-label:before,.was-validated .custom-control-input:valid:checked~.custom-control-label:before{background-color:#7be1a6;border-color:#7be1a6}.custom-control-input.is-valid:focus~.custom-control-label:before,.was-validated .custom-control-input:valid:focus~.custom-control-label:before{box-shadow:0 0 0 .2rem rgba(81,216,138,.25)}.custom-control-input.is-valid:focus:not(:checked)~.custom-control-label:before,.was-validated .custom-control-input:valid:focus:not(:checked)~.custom-control-label:before{border-color:#51d88a}.custom-file-input.is-valid~.custom-file-label,.was-validated .custom-file-input:valid~.custom-file-label{border-color:#51d88a}.custom-file-input.is-valid:focus~.custom-file-label,.was-validated .custom-file-input:valid:focus~.custom-file-label{border-color:#51d88a;box-shadow:0 0 0 .2rem rgba(81,216,138,.25)}.invalid-feedback{color:#ef5753;display:none;font-size:.875em;margin-top:.25rem;width:100%}.invalid-tooltip{background-color:rgba(239,87,83,.9);border-radius:.25rem;color:#fff;display:none;font-size:.83125rem;left:0;line-height:1.5;margin-top:.1rem;max-width:100%;padding:.25rem .5rem;position:absolute;top:100%;z-index:5}.form-row>.col>.invalid-tooltip,.form-row>[class*=col-]>.invalid-tooltip{left:5px}.is-invalid~.invalid-feedback,.is-invalid~.invalid-tooltip,.was-validated :invalid~.invalid-feedback,.was-validated :invalid~.invalid-tooltip{display:block}.form-control.is-invalid,.was-validated .form-control:invalid{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' fill='none' stroke='%23ef5753'%3E%3Ccircle cx='6' cy='6' r='4.5'/%3E%3Cpath stroke-linejoin='round' d='M5.8 3.6h.4L6 6.5z'/%3E%3Ccircle cx='6' cy='8.2' r='.6' fill='%23ef5753' stroke='none'/%3E%3C/svg%3E");background-position:right calc(.375em + .1875rem) center;background-repeat:no-repeat;background-size:calc(.75em + .375rem) calc(.75em + .375rem);border-color:#ef5753;padding-right:calc(1.5em + .75rem)!important}.form-control.is-invalid:focus,.was-validated .form-control:invalid:focus{border-color:#ef5753;box-shadow:0 0 0 .2rem rgba(239,87,83,.25)}.was-validated select.form-control:invalid,select.form-control.is-invalid{background-position:right 1.5rem center;padding-right:3rem!important}.was-validated textarea.form-control:invalid,textarea.form-control.is-invalid{background-position:top calc(.375em + .1875rem) right calc(.375em + .1875rem);padding-right:calc(1.5em + .75rem)}.custom-select.is-invalid,.was-validated .custom-select:invalid{background:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='4' height='5'%3E%3Cpath fill='%23343a40' d='M2 0 0 2h4zm0 5L0 3h4z'/%3E%3C/svg%3E") right .75rem center/8px 10px no-repeat,#fff url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' fill='none' stroke='%23ef5753'%3E%3Ccircle cx='6' cy='6' r='4.5'/%3E%3Cpath stroke-linejoin='round' d='M5.8 3.6h.4L6 6.5z'/%3E%3Ccircle cx='6' cy='8.2' r='.6' fill='%23ef5753' stroke='none'/%3E%3C/svg%3E") center right 1.75rem/calc(.75em + .375rem) calc(.75em + .375rem) no-repeat;border-color:#ef5753;padding-right:calc(.75em + 2.3125rem)!important}.custom-select.is-invalid:focus,.was-validated .custom-select:invalid:focus{border-color:#ef5753;box-shadow:0 0 0 .2rem rgba(239,87,83,.25)}.form-check-input.is-invalid~.form-check-label,.was-validated .form-check-input:invalid~.form-check-label{color:#ef5753}.form-check-input.is-invalid~.invalid-feedback,.form-check-input.is-invalid~.invalid-tooltip,.was-validated .form-check-input:invalid~.invalid-feedback,.was-validated .form-check-input:invalid~.invalid-tooltip{display:block}.custom-control-input.is-invalid~.custom-control-label,.was-validated .custom-control-input:invalid~.custom-control-label{color:#ef5753}.custom-control-input.is-invalid~.custom-control-label:before,.was-validated .custom-control-input:invalid~.custom-control-label:before{border-color:#ef5753}.custom-control-input.is-invalid:checked~.custom-control-label:before,.was-validated .custom-control-input:invalid:checked~.custom-control-label:before{background-color:#f38582;border-color:#f38582}.custom-control-input.is-invalid:focus~.custom-control-label:before,.was-validated .custom-control-input:invalid:focus~.custom-control-label:before{box-shadow:0 0 0 .2rem rgba(239,87,83,.25)}.custom-control-input.is-invalid:focus:not(:checked)~.custom-control-label:before,.was-validated .custom-control-input:invalid:focus:not(:checked)~.custom-control-label:before{border-color:#ef5753}.custom-file-input.is-invalid~.custom-file-label,.was-validated .custom-file-input:invalid~.custom-file-label{border-color:#ef5753}.custom-file-input.is-invalid:focus~.custom-file-label,.was-validated .custom-file-input:invalid:focus~.custom-file-label{border-color:#ef5753;box-shadow:0 0 0 .2rem rgba(239,87,83,.25)}.form-inline{align-items:center;display:flex;flex-flow:row wrap}.form-inline .form-check{width:100%}@media (min-width:2px){.form-inline label{justify-content:center}.form-inline .form-group,.form-inline label{align-items:center;display:flex;margin-bottom:0}.form-inline .form-group{flex:0 0 auto;flex-flow:row wrap}.form-inline .form-control{display:inline-block;vertical-align:middle;width:auto}.form-inline .form-control-plaintext{display:inline-block}.form-inline .custom-select,.form-inline .input-group{width:auto}.form-inline .form-check{align-items:center;display:flex;justify-content:center;padding-left:0;width:auto}.form-inline .form-check-input{flex-shrink:0;margin-left:0;margin-right:.25rem;margin-top:0;position:relative}.form-inline .custom-control{align-items:center;justify-content:center}.form-inline .custom-control-label{margin-bottom:0}}.btn{background-color:transparent;border:1px solid transparent;border-radius:.25rem;color:#212529;display:inline-block;font-size:.95rem;font-weight:400;line-height:1.5;padding:.375rem .75rem;text-align:center;transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;-webkit-user-select:none;-moz-user-select:none;user-select:none;vertical-align:middle}@media (prefers-reduced-motion:reduce){.btn{transition:none}}.btn:hover{color:#212529;text-decoration:none}.btn.focus,.btn:focus{box-shadow:0 0 0 .2rem rgba(119,70,236,.25);outline:0}.btn.disabled,.btn:disabled{opacity:.65}.btn:not(:disabled):not(.disabled){cursor:pointer}a.btn.disabled,fieldset:disabled a.btn{pointer-events:none}.btn-primary{background-color:#7746ec;border-color:#7746ec;color:#fff}.btn-primary.focus,.btn-primary:focus,.btn-primary:hover{background-color:#5e23e8;border-color:#5518e7;color:#fff}.btn-primary.focus,.btn-primary:focus{box-shadow:0 0 0 0 rgba(139,98,239,.5)}.btn-primary.disabled,.btn-primary:disabled{background-color:#7746ec;border-color:#7746ec;color:#fff}.btn-primary:not(:disabled):not(.disabled).active,.btn-primary:not(:disabled):not(.disabled):active,.show>.btn-primary.dropdown-toggle{background-color:#5518e7;border-color:#5117dc;color:#fff}.btn-primary:not(:disabled):not(.disabled).active:focus,.btn-primary:not(:disabled):not(.disabled):active:focus,.show>.btn-primary.dropdown-toggle:focus{box-shadow:0 0 0 0 rgba(139,98,239,.5)}.btn-secondary{background-color:#dae1e7;border-color:#dae1e7;color:#212529}.btn-secondary.focus,.btn-secondary:focus,.btn-secondary:hover{background-color:#c3ced8;border-color:#bbc8d3;color:#212529}.btn-secondary.focus,.btn-secondary:focus{box-shadow:0 0 0 0 rgba(190,197,203,.5)}.btn-secondary.disabled,.btn-secondary:disabled{background-color:#dae1e7;border-color:#dae1e7;color:#212529}.btn-secondary:not(:disabled):not(.disabled).active,.btn-secondary:not(:disabled):not(.disabled):active,.show>.btn-secondary.dropdown-toggle{background-color:#bbc8d3;border-color:#b3c2ce;color:#212529}.btn-secondary:not(:disabled):not(.disabled).active:focus,.btn-secondary:not(:disabled):not(.disabled):active:focus,.show>.btn-secondary.dropdown-toggle:focus{box-shadow:0 0 0 0 rgba(190,197,203,.5)}.btn-success{background-color:#51d88a;border-color:#51d88a;color:#212529}.btn-success.focus,.btn-success:focus,.btn-success:hover{background-color:#32d175;border-color:#2dc96f;color:#212529}.btn-success.focus,.btn-success:focus{box-shadow:0 0 0 0 rgba(74,189,123,.5)}.btn-success.disabled,.btn-success:disabled{background-color:#51d88a;border-color:#51d88a;color:#212529}.btn-success:not(:disabled):not(.disabled).active,.btn-success:not(:disabled):not(.disabled):active,.show>.btn-success.dropdown-toggle{background-color:#2dc96f;border-color:#2bbf69;color:#fff}.btn-success:not(:disabled):not(.disabled).active:focus,.btn-success:not(:disabled):not(.disabled):active:focus,.show>.btn-success.dropdown-toggle:focus{box-shadow:0 0 0 0 rgba(74,189,123,.5)}.btn-info{background-color:#bcdefa;border-color:#bcdefa;color:#212529}.btn-info.focus,.btn-info:focus,.btn-info:hover{background-color:#98ccf7;border-color:#8dc7f6;color:#212529}.btn-info.focus,.btn-info:focus{box-shadow:0 0 0 0 rgba(165,194,219,.5)}.btn-info.disabled,.btn-info:disabled{background-color:#bcdefa;border-color:#bcdefa;color:#212529}.btn-info:not(:disabled):not(.disabled).active,.btn-info:not(:disabled):not(.disabled):active,.show>.btn-info.dropdown-toggle{background-color:#8dc7f6;border-color:#81c1f6;color:#212529}.btn-info:not(:disabled):not(.disabled).active:focus,.btn-info:not(:disabled):not(.disabled):active:focus,.show>.btn-info.dropdown-toggle:focus{box-shadow:0 0 0 0 rgba(165,194,219,.5)}.btn-warning{background-color:#ffa260;border-color:#ffa260;color:#212529}.btn-warning.focus,.btn-warning:focus,.btn-warning:hover{background-color:#ff8c3a;border-color:#ff842d;color:#212529}.btn-warning.focus,.btn-warning:focus{box-shadow:0 0 0 0 rgba(222,143,88,.5)}.btn-warning.disabled,.btn-warning:disabled{background-color:#ffa260;border-color:#ffa260;color:#212529}.btn-warning:not(:disabled):not(.disabled).active,.btn-warning:not(:disabled):not(.disabled):active,.show>.btn-warning.dropdown-toggle{background-color:#ff842d;border-color:#ff7d20;color:#212529}.btn-warning:not(:disabled):not(.disabled).active:focus,.btn-warning:not(:disabled):not(.disabled):active:focus,.show>.btn-warning.dropdown-toggle:focus{box-shadow:0 0 0 0 rgba(222,143,88,.5)}.btn-danger{background-color:#ef5753;border-color:#ef5753;color:#fff}.btn-danger.focus,.btn-danger:focus,.btn-danger:hover{background-color:#ec3530;border-color:#eb2924;color:#fff}.btn-danger.focus,.btn-danger:focus{box-shadow:0 0 0 0 hsla(1,82%,69%,.5)}.btn-danger.disabled,.btn-danger:disabled{background-color:#ef5753;border-color:#ef5753;color:#fff}.btn-danger:not(:disabled):not(.disabled).active,.btn-danger:not(:disabled):not(.disabled):active,.show>.btn-danger.dropdown-toggle{background-color:#eb2924;border-color:#ea1e19;color:#fff}.btn-danger:not(:disabled):not(.disabled).active:focus,.btn-danger:not(:disabled):not(.disabled):active:focus,.show>.btn-danger.dropdown-toggle:focus{box-shadow:0 0 0 0 hsla(1,82%,69%,.5)}.btn-light{background-color:#f8f9fa;border-color:#f8f9fa;color:#212529}.btn-light.focus,.btn-light:focus,.btn-light:hover{background-color:#e2e6ea;border-color:#dae0e5;color:#212529}.btn-light.focus,.btn-light:focus{box-shadow:0 0 0 0 hsla(220,4%,85%,.5)}.btn-light.disabled,.btn-light:disabled{background-color:#f8f9fa;border-color:#f8f9fa;color:#212529}.btn-light:not(:disabled):not(.disabled).active,.btn-light:not(:disabled):not(.disabled):active,.show>.btn-light.dropdown-toggle{background-color:#dae0e5;border-color:#d3d9df;color:#212529}.btn-light:not(:disabled):not(.disabled).active:focus,.btn-light:not(:disabled):not(.disabled):active:focus,.show>.btn-light.dropdown-toggle:focus{box-shadow:0 0 0 0 hsla(220,4%,85%,.5)}.btn-dark{background-color:#343a40;border-color:#343a40;color:#fff}.btn-dark.focus,.btn-dark:focus,.btn-dark:hover{background-color:#23272b;border-color:#1d2124;color:#fff}.btn-dark.focus,.btn-dark:focus{box-shadow:0 0 0 0 rgba(82,88,93,.5)}.btn-dark.disabled,.btn-dark:disabled{background-color:#343a40;border-color:#343a40;color:#fff}.btn-dark:not(:disabled):not(.disabled).active,.btn-dark:not(:disabled):not(.disabled):active,.show>.btn-dark.dropdown-toggle{background-color:#1d2124;border-color:#171a1d;color:#fff}.btn-dark:not(:disabled):not(.disabled).active:focus,.btn-dark:not(:disabled):not(.disabled):active:focus,.show>.btn-dark.dropdown-toggle:focus{box-shadow:0 0 0 0 rgba(82,88,93,.5)}.btn-outline-primary{border-color:#7746ec;color:#7746ec}.btn-outline-primary:hover{background-color:#7746ec;border-color:#7746ec;color:#fff}.btn-outline-primary.focus,.btn-outline-primary:focus{box-shadow:0 0 0 0 rgba(119,70,236,.5)}.btn-outline-primary.disabled,.btn-outline-primary:disabled{background-color:transparent;color:#7746ec}.btn-outline-primary:not(:disabled):not(.disabled).active,.btn-outline-primary:not(:disabled):not(.disabled):active,.show>.btn-outline-primary.dropdown-toggle{background-color:#7746ec;border-color:#7746ec;color:#fff}.btn-outline-primary:not(:disabled):not(.disabled).active:focus,.btn-outline-primary:not(:disabled):not(.disabled):active:focus,.show>.btn-outline-primary.dropdown-toggle:focus{box-shadow:0 0 0 0 rgba(119,70,236,.5)}.btn-outline-secondary{border-color:#dae1e7;color:#dae1e7}.btn-outline-secondary:hover{background-color:#dae1e7;border-color:#dae1e7;color:#212529}.btn-outline-secondary.focus,.btn-outline-secondary:focus{box-shadow:0 0 0 0 rgba(218,225,231,.5)}.btn-outline-secondary.disabled,.btn-outline-secondary:disabled{background-color:transparent;color:#dae1e7}.btn-outline-secondary:not(:disabled):not(.disabled).active,.btn-outline-secondary:not(:disabled):not(.disabled):active,.show>.btn-outline-secondary.dropdown-toggle{background-color:#dae1e7;border-color:#dae1e7;color:#212529}.btn-outline-secondary:not(:disabled):not(.disabled).active:focus,.btn-outline-secondary:not(:disabled):not(.disabled):active:focus,.show>.btn-outline-secondary.dropdown-toggle:focus{box-shadow:0 0 0 0 rgba(218,225,231,.5)}.btn-outline-success{border-color:#51d88a;color:#51d88a}.btn-outline-success:hover{background-color:#51d88a;border-color:#51d88a;color:#212529}.btn-outline-success.focus,.btn-outline-success:focus{box-shadow:0 0 0 0 rgba(81,216,138,.5)}.btn-outline-success.disabled,.btn-outline-success:disabled{background-color:transparent;color:#51d88a}.btn-outline-success:not(:disabled):not(.disabled).active,.btn-outline-success:not(:disabled):not(.disabled):active,.show>.btn-outline-success.dropdown-toggle{background-color:#51d88a;border-color:#51d88a;color:#212529}.btn-outline-success:not(:disabled):not(.disabled).active:focus,.btn-outline-success:not(:disabled):not(.disabled):active:focus,.show>.btn-outline-success.dropdown-toggle:focus{box-shadow:0 0 0 0 rgba(81,216,138,.5)}.btn-outline-info{border-color:#bcdefa;color:#bcdefa}.btn-outline-info:hover{background-color:#bcdefa;border-color:#bcdefa;color:#212529}.btn-outline-info.focus,.btn-outline-info:focus{box-shadow:0 0 0 0 rgba(188,222,250,.5)}.btn-outline-info.disabled,.btn-outline-info:disabled{background-color:transparent;color:#bcdefa}.btn-outline-info:not(:disabled):not(.disabled).active,.btn-outline-info:not(:disabled):not(.disabled):active,.show>.btn-outline-info.dropdown-toggle{background-color:#bcdefa;border-color:#bcdefa;color:#212529}.btn-outline-info:not(:disabled):not(.disabled).active:focus,.btn-outline-info:not(:disabled):not(.disabled):active:focus,.show>.btn-outline-info.dropdown-toggle:focus{box-shadow:0 0 0 0 rgba(188,222,250,.5)}.btn-outline-warning{border-color:#ffa260;color:#ffa260}.btn-outline-warning:hover{background-color:#ffa260;border-color:#ffa260;color:#212529}.btn-outline-warning.focus,.btn-outline-warning:focus{box-shadow:0 0 0 0 rgba(255,162,96,.5)}.btn-outline-warning.disabled,.btn-outline-warning:disabled{background-color:transparent;color:#ffa260}.btn-outline-warning:not(:disabled):not(.disabled).active,.btn-outline-warning:not(:disabled):not(.disabled):active,.show>.btn-outline-warning.dropdown-toggle{background-color:#ffa260;border-color:#ffa260;color:#212529}.btn-outline-warning:not(:disabled):not(.disabled).active:focus,.btn-outline-warning:not(:disabled):not(.disabled):active:focus,.show>.btn-outline-warning.dropdown-toggle:focus{box-shadow:0 0 0 0 rgba(255,162,96,.5)}.btn-outline-danger{border-color:#ef5753;color:#ef5753}.btn-outline-danger:hover{background-color:#ef5753;border-color:#ef5753;color:#fff}.btn-outline-danger.focus,.btn-outline-danger:focus{box-shadow:0 0 0 0 rgba(239,87,83,.5)}.btn-outline-danger.disabled,.btn-outline-danger:disabled{background-color:transparent;color:#ef5753}.btn-outline-danger:not(:disabled):not(.disabled).active,.btn-outline-danger:not(:disabled):not(.disabled):active,.show>.btn-outline-danger.dropdown-toggle{background-color:#ef5753;border-color:#ef5753;color:#fff}.btn-outline-danger:not(:disabled):not(.disabled).active:focus,.btn-outline-danger:not(:disabled):not(.disabled):active:focus,.show>.btn-outline-danger.dropdown-toggle:focus{box-shadow:0 0 0 0 rgba(239,87,83,.5)}.btn-outline-light{border-color:#f8f9fa;color:#f8f9fa}.btn-outline-light:hover{background-color:#f8f9fa;border-color:#f8f9fa;color:#212529}.btn-outline-light.focus,.btn-outline-light:focus{box-shadow:0 0 0 0 rgba(248,249,250,.5)}.btn-outline-light.disabled,.btn-outline-light:disabled{background-color:transparent;color:#f8f9fa}.btn-outline-light:not(:disabled):not(.disabled).active,.btn-outline-light:not(:disabled):not(.disabled):active,.show>.btn-outline-light.dropdown-toggle{background-color:#f8f9fa;border-color:#f8f9fa;color:#212529}.btn-outline-light:not(:disabled):not(.disabled).active:focus,.btn-outline-light:not(:disabled):not(.disabled):active:focus,.show>.btn-outline-light.dropdown-toggle:focus{box-shadow:0 0 0 0 rgba(248,249,250,.5)}.btn-outline-dark{border-color:#343a40;color:#343a40}.btn-outline-dark:hover{background-color:#343a40;border-color:#343a40;color:#fff}.btn-outline-dark.focus,.btn-outline-dark:focus{box-shadow:0 0 0 0 rgba(52,58,64,.5)}.btn-outline-dark.disabled,.btn-outline-dark:disabled{background-color:transparent;color:#343a40}.btn-outline-dark:not(:disabled):not(.disabled).active,.btn-outline-dark:not(:disabled):not(.disabled):active,.show>.btn-outline-dark.dropdown-toggle{background-color:#343a40;border-color:#343a40;color:#fff}.btn-outline-dark:not(:disabled):not(.disabled).active:focus,.btn-outline-dark:not(:disabled):not(.disabled):active:focus,.show>.btn-outline-dark.dropdown-toggle:focus{box-shadow:0 0 0 0 rgba(52,58,64,.5)}.btn-link{color:#7746ec;font-weight:400;text-decoration:none}.btn-link:hover{color:#4d15d0}.btn-link.focus,.btn-link:focus,.btn-link:hover{text-decoration:underline}.btn-link.disabled,.btn-link:disabled{color:#6c757d;pointer-events:none}.btn-group-lg>.btn,.btn-lg{border-radius:.3rem;font-size:1.1875rem;line-height:1.5;padding:.5rem 1rem}.btn-group-sm>.btn,.btn-sm{border-radius:.2rem;font-size:.83125rem;line-height:1.5;padding:.25rem .5rem}.btn-block{display:block;width:100%}.btn-block+.btn-block{margin-top:.5rem}input[type=button].btn-block,input[type=reset].btn-block,input[type=submit].btn-block{width:100%}.fade{transition:opacity .15s linear}@media (prefers-reduced-motion:reduce){.fade{transition:none}}.fade:not(.show){opacity:0}.collapse:not(.show){display:none}.collapsing{height:0;overflow:hidden;position:relative;transition:height .35s ease}@media (prefers-reduced-motion:reduce){.collapsing{transition:none}}.collapsing.width{height:auto;transition:width .35s ease;width:0}@media (prefers-reduced-motion:reduce){.collapsing.width{transition:none}}.dropdown,.dropleft,.dropright,.dropup{position:relative}.dropdown-toggle{white-space:nowrap}.dropdown-toggle:after{border-bottom:0;border-left:.3em solid transparent;border-right:.3em solid transparent;border-top:.3em solid;content:"";display:inline-block;margin-left:.255em;vertical-align:.255em}.dropdown-toggle:empty:after{margin-left:0}.dropdown-menu{background-clip:padding-box;background-color:#fff;border:1px solid rgba(0,0,0,.15);border-radius:.25rem;color:#212529;display:none;float:left;font-size:.95rem;left:0;list-style:none;margin:.125rem 0 0;min-width:10rem;padding:.5rem 0;position:absolute;text-align:left;top:100%;z-index:1000}.dropdown-menu-left{left:0;right:auto}.dropdown-menu-right{left:auto;right:0}@media (min-width:2px){.dropdown-menu-sm-left{left:0;right:auto}.dropdown-menu-sm-right{left:auto;right:0}}@media (min-width:8px){.dropdown-menu-md-left{left:0;right:auto}.dropdown-menu-md-right{left:auto;right:0}}@media (min-width:9px){.dropdown-menu-lg-left{left:0;right:auto}.dropdown-menu-lg-right{left:auto;right:0}}@media (min-width:10px){.dropdown-menu-xl-left{left:0;right:auto}.dropdown-menu-xl-right{left:auto;right:0}}.dropup .dropdown-menu{bottom:100%;margin-bottom:.125rem;margin-top:0;top:auto}.dropup .dropdown-toggle:after{border-bottom:.3em solid;border-left:.3em solid transparent;border-right:.3em solid transparent;border-top:0;content:"";display:inline-block;margin-left:.255em;vertical-align:.255em}.dropup .dropdown-toggle:empty:after{margin-left:0}.dropright .dropdown-menu{left:100%;margin-left:.125rem;margin-top:0;right:auto;top:0}.dropright .dropdown-toggle:after{border-bottom:.3em solid transparent;border-left:.3em solid;border-right:0;border-top:.3em solid transparent;content:"";display:inline-block;margin-left:.255em;vertical-align:.255em}.dropright .dropdown-toggle:empty:after{margin-left:0}.dropright .dropdown-toggle:after{vertical-align:0}.dropleft .dropdown-menu{left:auto;margin-right:.125rem;margin-top:0;right:100%;top:0}.dropleft .dropdown-toggle:after{content:"";display:inline-block;display:none;margin-left:.255em;vertical-align:.255em}.dropleft .dropdown-toggle:before{border-bottom:.3em solid transparent;border-right:.3em solid;border-top:.3em solid transparent;content:"";display:inline-block;margin-right:.255em;vertical-align:.255em}.dropleft .dropdown-toggle:empty:after{margin-left:0}.dropleft .dropdown-toggle:before{vertical-align:0}.dropdown-menu[x-placement^=bottom],.dropdown-menu[x-placement^=left],.dropdown-menu[x-placement^=right],.dropdown-menu[x-placement^=top]{bottom:auto;right:auto}.dropdown-divider{border-top:1px solid #e9ecef;height:0;margin:.5rem 0;overflow:hidden}.dropdown-item{background-color:transparent;border:0;clear:both;color:#212529;display:block;font-weight:400;padding:.25rem 1.5rem;text-align:inherit;white-space:nowrap;width:100%}.dropdown-item:focus,.dropdown-item:hover{background-color:#e9ecef;color:#16181b;text-decoration:none}.dropdown-item.active,.dropdown-item:active{background-color:#7746ec;color:#fff;text-decoration:none}.dropdown-item.disabled,.dropdown-item:disabled{background-color:transparent;color:#adb5bd;pointer-events:none}.dropdown-menu.show{display:block}.dropdown-header{color:#6c757d;display:block;font-size:.83125rem;margin-bottom:0;padding:.5rem 1.5rem;white-space:nowrap}.dropdown-item-text{color:#212529;display:block;padding:.25rem 1.5rem}.btn-group,.btn-group-vertical{display:inline-flex;position:relative;vertical-align:middle}.btn-group-vertical>.btn,.btn-group>.btn{flex:1 1 auto;position:relative}.btn-group-vertical>.btn.active,.btn-group-vertical>.btn:active,.btn-group-vertical>.btn:focus,.btn-group-vertical>.btn:hover,.btn-group>.btn.active,.btn-group>.btn:active,.btn-group>.btn:focus,.btn-group>.btn:hover{z-index:1}.btn-toolbar{display:flex;flex-wrap:wrap;justify-content:flex-start}.btn-toolbar .input-group{width:auto}.btn-group>.btn-group:not(:first-child),.btn-group>.btn:not(:first-child){margin-left:-1px}.btn-group>.btn-group:not(:last-child)>.btn,.btn-group>.btn:not(:last-child):not(.dropdown-toggle){border-bottom-right-radius:0;border-top-right-radius:0}.btn-group>.btn-group:not(:first-child)>.btn,.btn-group>.btn:not(:first-child){border-bottom-left-radius:0;border-top-left-radius:0}.dropdown-toggle-split{padding-left:.5625rem;padding-right:.5625rem}.dropdown-toggle-split:after,.dropright .dropdown-toggle-split:after,.dropup .dropdown-toggle-split:after{margin-left:0}.dropleft .dropdown-toggle-split:before{margin-right:0}.btn-group-sm>.btn+.dropdown-toggle-split,.btn-sm+.dropdown-toggle-split{padding-left:.375rem;padding-right:.375rem}.btn-group-lg>.btn+.dropdown-toggle-split,.btn-lg+.dropdown-toggle-split{padding-left:.75rem;padding-right:.75rem}.btn-group-vertical{align-items:flex-start;flex-direction:column;justify-content:center}.btn-group-vertical>.btn,.btn-group-vertical>.btn-group{width:100%}.btn-group-vertical>.btn-group:not(:first-child),.btn-group-vertical>.btn:not(:first-child){margin-top:-1px}.btn-group-vertical>.btn-group:not(:last-child)>.btn,.btn-group-vertical>.btn:not(:last-child):not(.dropdown-toggle){border-bottom-left-radius:0;border-bottom-right-radius:0}.btn-group-vertical>.btn-group:not(:first-child)>.btn,.btn-group-vertical>.btn:not(:first-child){border-top-left-radius:0;border-top-right-radius:0}.btn-group-toggle>.btn,.btn-group-toggle>.btn-group>.btn{margin-bottom:0}.btn-group-toggle>.btn input[type=checkbox],.btn-group-toggle>.btn input[type=radio],.btn-group-toggle>.btn-group>.btn input[type=checkbox],.btn-group-toggle>.btn-group>.btn input[type=radio]{clip:rect(0,0,0,0);pointer-events:none;position:absolute}.input-group{align-items:stretch;display:flex;flex-wrap:wrap;position:relative;width:100%}.input-group>.custom-file,.input-group>.custom-select,.input-group>.form-control,.input-group>.form-control-plaintext{flex:1 1 auto;margin-bottom:0;min-width:0;position:relative;width:1%}.input-group>.custom-file+.custom-file,.input-group>.custom-file+.custom-select,.input-group>.custom-file+.form-control,.input-group>.custom-select+.custom-file,.input-group>.custom-select+.custom-select,.input-group>.custom-select+.form-control,.input-group>.form-control+.custom-file,.input-group>.form-control+.custom-select,.input-group>.form-control+.form-control,.input-group>.form-control-plaintext+.custom-file,.input-group>.form-control-plaintext+.custom-select,.input-group>.form-control-plaintext+.form-control{margin-left:-1px}.input-group>.custom-file .custom-file-input:focus~.custom-file-label,.input-group>.custom-select:focus,.input-group>.form-control:focus{z-index:3}.input-group>.custom-file .custom-file-input:focus{z-index:4}.input-group>.custom-select:not(:first-child),.input-group>.form-control:not(:first-child){border-bottom-left-radius:0;border-top-left-radius:0}.input-group>.custom-file{align-items:center;display:flex}.input-group>.custom-file:not(:last-child) .custom-file-label,.input-group>.custom-file:not(:last-child) .custom-file-label:after{border-bottom-right-radius:0;border-top-right-radius:0}.input-group>.custom-file:not(:first-child) .custom-file-label{border-bottom-left-radius:0;border-top-left-radius:0}.input-group.has-validation>.custom-file:nth-last-child(n+3) .custom-file-label,.input-group.has-validation>.custom-file:nth-last-child(n+3) .custom-file-label:after,.input-group.has-validation>.custom-select:nth-last-child(n+3),.input-group.has-validation>.form-control:nth-last-child(n+3),.input-group:not(.has-validation)>.custom-file:not(:last-child) .custom-file-label,.input-group:not(.has-validation)>.custom-file:not(:last-child) .custom-file-label:after,.input-group:not(.has-validation)>.custom-select:not(:last-child),.input-group:not(.has-validation)>.form-control:not(:last-child){border-bottom-right-radius:0;border-top-right-radius:0}.input-group-append,.input-group-prepend{display:flex}.input-group-append .btn,.input-group-prepend .btn{position:relative;z-index:2}.input-group-append .btn:focus,.input-group-prepend .btn:focus{z-index:3}.input-group-append .btn+.btn,.input-group-append .btn+.input-group-text,.input-group-append .input-group-text+.btn,.input-group-append .input-group-text+.input-group-text,.input-group-prepend .btn+.btn,.input-group-prepend .btn+.input-group-text,.input-group-prepend .input-group-text+.btn,.input-group-prepend .input-group-text+.input-group-text{margin-left:-1px}.input-group-prepend{margin-right:-1px}.input-group-append{margin-left:-1px}.input-group-text{align-items:center;background-color:#e9ecef;border:1px solid #ced4da;border-radius:.25rem;color:#495057;display:flex;font-size:.95rem;font-weight:400;line-height:1.5;margin-bottom:0;padding:.375rem .75rem;text-align:center;white-space:nowrap}.input-group-text input[type=checkbox],.input-group-text input[type=radio]{margin-top:0}.input-group-lg>.custom-select,.input-group-lg>.form-control:not(textarea){height:calc(1.5em + 1rem + 2px)}.input-group-lg>.custom-select,.input-group-lg>.form-control,.input-group-lg>.input-group-append>.btn,.input-group-lg>.input-group-append>.input-group-text,.input-group-lg>.input-group-prepend>.btn,.input-group-lg>.input-group-prepend>.input-group-text{border-radius:.3rem;font-size:1.1875rem;line-height:1.5;padding:.5rem 1rem}.input-group-sm>.custom-select,.input-group-sm>.form-control:not(textarea){height:calc(1.5em + .5rem + 2px)}.input-group-sm>.custom-select,.input-group-sm>.form-control,.input-group-sm>.input-group-append>.btn,.input-group-sm>.input-group-append>.input-group-text,.input-group-sm>.input-group-prepend>.btn,.input-group-sm>.input-group-prepend>.input-group-text{border-radius:.2rem;font-size:.83125rem;line-height:1.5;padding:.25rem .5rem}.input-group-lg>.custom-select,.input-group-sm>.custom-select{padding-right:1.75rem}.input-group.has-validation>.input-group-append:nth-last-child(n+3)>.btn,.input-group.has-validation>.input-group-append:nth-last-child(n+3)>.input-group-text,.input-group:not(.has-validation)>.input-group-append:not(:last-child)>.btn,.input-group:not(.has-validation)>.input-group-append:not(:last-child)>.input-group-text,.input-group>.input-group-append:last-child>.btn:not(:last-child):not(.dropdown-toggle),.input-group>.input-group-append:last-child>.input-group-text:not(:last-child),.input-group>.input-group-prepend>.btn,.input-group>.input-group-prepend>.input-group-text{border-bottom-right-radius:0;border-top-right-radius:0}.input-group>.input-group-append>.btn,.input-group>.input-group-append>.input-group-text,.input-group>.input-group-prepend:first-child>.btn:not(:first-child),.input-group>.input-group-prepend:first-child>.input-group-text:not(:first-child),.input-group>.input-group-prepend:not(:first-child)>.btn,.input-group>.input-group-prepend:not(:first-child)>.input-group-text{border-bottom-left-radius:0;border-top-left-radius:0}.custom-control{display:block;min-height:1.425rem;padding-left:1.5rem;position:relative;-webkit-print-color-adjust:exact;print-color-adjust:exact;z-index:1}.custom-control-inline{display:inline-flex;margin-right:1rem}.custom-control-input{height:1.2125rem;left:0;opacity:0;position:absolute;width:1rem;z-index:-1}.custom-control-input:checked~.custom-control-label:before{background-color:#7746ec;border-color:#7746ec;color:#fff}.custom-control-input:focus~.custom-control-label:before{box-shadow:0 0 0 .2rem rgba(119,70,236,.25)}.custom-control-input:focus:not(:checked)~.custom-control-label:before{border-color:#ccbaf8}.custom-control-input:not(:disabled):active~.custom-control-label:before{background-color:#eee8fd;border-color:#eee8fd;color:#fff}.custom-control-input:disabled~.custom-control-label,.custom-control-input[disabled]~.custom-control-label{color:#6c757d}.custom-control-input:disabled~.custom-control-label:before,.custom-control-input[disabled]~.custom-control-label:before{background-color:#e9ecef}.custom-control-label{margin-bottom:0;position:relative;vertical-align:top}.custom-control-label:before{background-color:#fff;border:1px solid #adb5bd;pointer-events:none}.custom-control-label:after,.custom-control-label:before{content:"";display:block;height:1rem;left:-1.5rem;position:absolute;top:.2125rem;width:1rem}.custom-control-label:after{background:50%/50% 50% no-repeat}.custom-checkbox .custom-control-label:before{border-radius:.25rem}.custom-checkbox .custom-control-input:checked~.custom-control-label:after{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='8' height='8'%3E%3Cpath fill='%23fff' d='m6.564.75-3.59 3.612-1.538-1.55L0 4.26l2.974 2.99L8 2.193z'/%3E%3C/svg%3E")}.custom-checkbox .custom-control-input:indeterminate~.custom-control-label:before{background-color:#7746ec;border-color:#7746ec}.custom-checkbox .custom-control-input:indeterminate~.custom-control-label:after{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='4' height='4'%3E%3Cpath stroke='%23fff' d='M0 2h4'/%3E%3C/svg%3E")}.custom-checkbox .custom-control-input:disabled:checked~.custom-control-label:before{background-color:rgba(119,70,236,.5)}.custom-checkbox .custom-control-input:disabled:indeterminate~.custom-control-label:before{background-color:rgba(119,70,236,.5)}.custom-radio .custom-control-label:before{border-radius:50%}.custom-radio .custom-control-input:checked~.custom-control-label:after{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='-4 -4 8 8'%3E%3Ccircle r='3' fill='%23fff'/%3E%3C/svg%3E")}.custom-radio .custom-control-input:disabled:checked~.custom-control-label:before{background-color:rgba(119,70,236,.5)}.custom-switch{padding-left:2.25rem}.custom-switch .custom-control-label:before{border-radius:.5rem;left:-2.25rem;pointer-events:all;width:1.75rem}.custom-switch .custom-control-label:after{background-color:#adb5bd;border-radius:.5rem;height:calc(1rem - 4px);left:calc(-2.25rem + 2px);top:calc(.2125rem + 2px);transition:transform .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;width:calc(1rem - 4px)}@media (prefers-reduced-motion:reduce){.custom-switch .custom-control-label:after{transition:none}}.custom-switch .custom-control-input:checked~.custom-control-label:after{background-color:#fff;transform:translateX(.75rem)}.custom-switch .custom-control-input:disabled:checked~.custom-control-label:before{background-color:rgba(119,70,236,.5)}.custom-select{-webkit-appearance:none;-moz-appearance:none;appearance:none;background:#fff url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='4' height='5'%3E%3Cpath fill='%23343a40' d='M2 0 0 2h4zm0 5L0 3h4z'/%3E%3C/svg%3E") right .75rem center/8px 10px no-repeat;border:1px solid #ced4da;border-radius:.25rem;color:#495057;display:inline-block;font-size:.95rem;font-weight:400;height:calc(1.5em + .75rem + 2px);line-height:1.5;padding:.375rem 1.75rem .375rem .75rem;vertical-align:middle;width:100%}.custom-select:focus{border-color:#ccbaf8;box-shadow:0 0 0 .2rem rgba(119,70,236,.25);outline:0}.custom-select:focus::-ms-value{background-color:#fff;color:#495057}.custom-select[multiple],.custom-select[size]:not([size="1"]){background-image:none;height:auto;padding-right:.75rem}.custom-select:disabled{background-color:#e9ecef;color:#6c757d}.custom-select::-ms-expand{display:none}.custom-select:-moz-focusring{color:transparent;text-shadow:0 0 0 #495057}.custom-select-sm{font-size:.83125rem;height:calc(1.5em + .5rem + 2px);padding-bottom:.25rem;padding-left:.5rem;padding-top:.25rem}.custom-select-lg{font-size:1.1875rem;height:calc(1.5em + 1rem + 2px);padding-bottom:.5rem;padding-left:1rem;padding-top:.5rem}.custom-file{display:inline-block;margin-bottom:0}.custom-file,.custom-file-input{height:calc(1.5em + .75rem + 2px);position:relative;width:100%}.custom-file-input{margin:0;opacity:0;overflow:hidden;z-index:2}.custom-file-input:focus~.custom-file-label{border-color:#ccbaf8;box-shadow:0 0 0 .2rem rgba(119,70,236,.25)}.custom-file-input:disabled~.custom-file-label,.custom-file-input[disabled]~.custom-file-label{background-color:#e9ecef}.custom-file-input:lang(en)~.custom-file-label:after{content:"Browse"}.custom-file-input~.custom-file-label[data-browse]:after{content:attr(data-browse)}.custom-file-label{background-color:#fff;border:1px solid #ced4da;border-radius:.25rem;font-weight:400;height:calc(1.5em + .75rem + 2px);left:0;overflow:hidden;z-index:1}.custom-file-label,.custom-file-label:after{color:#495057;line-height:1.5;padding:.375rem .75rem;position:absolute;right:0;top:0}.custom-file-label:after{background-color:#e9ecef;border-left:inherit;border-radius:0 .25rem .25rem 0;bottom:0;content:"Browse";display:block;height:calc(1.5em + .75rem);z-index:3}.custom-range{-webkit-appearance:none;-moz-appearance:none;appearance:none;background-color:transparent;height:1.4rem;padding:0;width:100%}.custom-range:focus{outline:0}.custom-range:focus::-webkit-slider-thumb{box-shadow:0 0 0 1px #ebebeb,0 0 0 .2rem rgba(119,70,236,.25)}.custom-range:focus::-moz-range-thumb{box-shadow:0 0 0 1px #ebebeb,0 0 0 .2rem rgba(119,70,236,.25)}.custom-range:focus::-ms-thumb{box-shadow:0 0 0 1px #ebebeb,0 0 0 .2rem rgba(119,70,236,.25)}.custom-range::-moz-focus-outer{border:0}.custom-range::-webkit-slider-thumb{-webkit-appearance:none;appearance:none;background-color:#7746ec;border:0;border-radius:1rem;height:1rem;margin-top:-.25rem;-webkit-transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;width:1rem}@media (prefers-reduced-motion:reduce){.custom-range::-webkit-slider-thumb{-webkit-transition:none;transition:none}}.custom-range::-webkit-slider-thumb:active{background-color:#eee8fd}.custom-range::-webkit-slider-runnable-track{background-color:#dee2e6;border-color:transparent;border-radius:1rem;color:transparent;cursor:pointer;height:.5rem;width:100%}.custom-range::-moz-range-thumb{-moz-appearance:none;appearance:none;background-color:#7746ec;border:0;border-radius:1rem;height:1rem;-moz-transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;width:1rem}@media (prefers-reduced-motion:reduce){.custom-range::-moz-range-thumb{-moz-transition:none;transition:none}}.custom-range::-moz-range-thumb:active{background-color:#eee8fd}.custom-range::-moz-range-track{background-color:#dee2e6;border-color:transparent;border-radius:1rem;color:transparent;cursor:pointer;height:.5rem;width:100%}.custom-range::-ms-thumb{appearance:none;background-color:#7746ec;border:0;border-radius:1rem;height:1rem;margin-left:.2rem;margin-right:.2rem;margin-top:0;-ms-transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;width:1rem}@media (prefers-reduced-motion:reduce){.custom-range::-ms-thumb{-ms-transition:none;transition:none}}.custom-range::-ms-thumb:active{background-color:#eee8fd}.custom-range::-ms-track{background-color:transparent;border-color:transparent;border-width:.5rem;color:transparent;cursor:pointer;height:.5rem;width:100%}.custom-range::-ms-fill-lower,.custom-range::-ms-fill-upper{background-color:#dee2e6;border-radius:1rem}.custom-range::-ms-fill-upper{margin-right:15px}.custom-range:disabled::-webkit-slider-thumb{background-color:#adb5bd}.custom-range:disabled::-webkit-slider-runnable-track{cursor:default}.custom-range:disabled::-moz-range-thumb{background-color:#adb5bd}.custom-range:disabled::-moz-range-track{cursor:default}.custom-range:disabled::-ms-thumb{background-color:#adb5bd}.custom-control-label:before,.custom-file-label,.custom-select{transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out}@media (prefers-reduced-motion:reduce){.custom-control-label:before,.custom-file-label,.custom-select{transition:none}}.nav{display:flex;flex-wrap:wrap;list-style:none;margin-bottom:0;padding-left:0}.nav-link{display:block;padding:.5rem 1rem}.nav-link:focus,.nav-link:hover{text-decoration:none}.nav-link.disabled{color:#6c757d;cursor:default;pointer-events:none}.nav-tabs{border-bottom:1px solid #dee2e6}.nav-tabs .nav-link{background-color:transparent;border:1px solid transparent;border-top-left-radius:.25rem;border-top-right-radius:.25rem;margin-bottom:-1px}.nav-tabs .nav-link:focus,.nav-tabs .nav-link:hover{border-color:#e9ecef #e9ecef #dee2e6;isolation:isolate}.nav-tabs .nav-link.disabled{background-color:transparent;border-color:transparent;color:#6c757d}.nav-tabs .nav-item.show .nav-link,.nav-tabs .nav-link.active{background-color:#ebebeb;border-color:#dee2e6 #dee2e6 #ebebeb;color:#495057}.nav-tabs .dropdown-menu{border-top-left-radius:0;border-top-right-radius:0;margin-top:-1px}.nav-pills .nav-link{background:none;border:0;border-radius:.25rem}.nav-pills .nav-link.active,.nav-pills .show>.nav-link{background-color:#7746ec;color:#fff}.nav-fill .nav-item,.nav-fill>.nav-link{flex:1 1 auto;text-align:center}.nav-justified .nav-item,.nav-justified>.nav-link{flex-basis:0;flex-grow:1;text-align:center}.tab-content>.tab-pane{display:none}.tab-content>.active{display:block}.navbar{padding:.5rem 1rem;position:relative}.navbar,.navbar .container,.navbar .container-fluid,.navbar .container-lg,.navbar .container-md,.navbar .container-sm,.navbar .container-xl{align-items:center;display:flex;flex-wrap:wrap;justify-content:space-between}.navbar-brand{display:inline-block;font-size:1.1875rem;line-height:inherit;margin-right:1rem;padding-bottom:.321875rem;padding-top:.321875rem;white-space:nowrap}.navbar-brand:focus,.navbar-brand:hover{text-decoration:none}.navbar-nav{display:flex;flex-direction:column;list-style:none;margin-bottom:0;padding-left:0}.navbar-nav .nav-link{padding-left:0;padding-right:0}.navbar-nav .dropdown-menu{float:none;position:static}.navbar-text{display:inline-block;padding-bottom:.5rem;padding-top:.5rem}.navbar-collapse{align-items:center;flex-basis:100%;flex-grow:1}.navbar-toggler{background-color:transparent;border:1px solid transparent;border-radius:.25rem;font-size:1.1875rem;line-height:1;padding:.25rem .75rem}.navbar-toggler:focus,.navbar-toggler:hover{text-decoration:none}.navbar-toggler-icon{background:50%/100% 100% no-repeat;content:"";display:inline-block;height:1.5em;vertical-align:middle;width:1.5em}.navbar-nav-scroll{max-height:75vh;overflow-y:auto}@media (max-width:1.98px){.navbar-expand-sm>.container,.navbar-expand-sm>.container-fluid,.navbar-expand-sm>.container-lg,.navbar-expand-sm>.container-md,.navbar-expand-sm>.container-sm,.navbar-expand-sm>.container-xl{padding-left:0;padding-right:0}}@media (min-width:2px){.navbar-expand-sm{flex-flow:row nowrap;justify-content:flex-start}.navbar-expand-sm .navbar-nav{flex-direction:row}.navbar-expand-sm .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-sm .navbar-nav .nav-link{padding-left:.5rem;padding-right:.5rem}.navbar-expand-sm>.container,.navbar-expand-sm>.container-fluid,.navbar-expand-sm>.container-lg,.navbar-expand-sm>.container-md,.navbar-expand-sm>.container-sm,.navbar-expand-sm>.container-xl{flex-wrap:nowrap}.navbar-expand-sm .navbar-nav-scroll{overflow:visible}.navbar-expand-sm .navbar-collapse{display:flex!important;flex-basis:auto}.navbar-expand-sm .navbar-toggler{display:none}}@media (max-width:7.98px){.navbar-expand-md>.container,.navbar-expand-md>.container-fluid,.navbar-expand-md>.container-lg,.navbar-expand-md>.container-md,.navbar-expand-md>.container-sm,.navbar-expand-md>.container-xl{padding-left:0;padding-right:0}}@media (min-width:8px){.navbar-expand-md{flex-flow:row nowrap;justify-content:flex-start}.navbar-expand-md .navbar-nav{flex-direction:row}.navbar-expand-md .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-md .navbar-nav .nav-link{padding-left:.5rem;padding-right:.5rem}.navbar-expand-md>.container,.navbar-expand-md>.container-fluid,.navbar-expand-md>.container-lg,.navbar-expand-md>.container-md,.navbar-expand-md>.container-sm,.navbar-expand-md>.container-xl{flex-wrap:nowrap}.navbar-expand-md .navbar-nav-scroll{overflow:visible}.navbar-expand-md .navbar-collapse{display:flex!important;flex-basis:auto}.navbar-expand-md .navbar-toggler{display:none}}@media (max-width:8.98px){.navbar-expand-lg>.container,.navbar-expand-lg>.container-fluid,.navbar-expand-lg>.container-lg,.navbar-expand-lg>.container-md,.navbar-expand-lg>.container-sm,.navbar-expand-lg>.container-xl{padding-left:0;padding-right:0}}@media (min-width:9px){.navbar-expand-lg{flex-flow:row nowrap;justify-content:flex-start}.navbar-expand-lg .navbar-nav{flex-direction:row}.navbar-expand-lg .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-lg .navbar-nav .nav-link{padding-left:.5rem;padding-right:.5rem}.navbar-expand-lg>.container,.navbar-expand-lg>.container-fluid,.navbar-expand-lg>.container-lg,.navbar-expand-lg>.container-md,.navbar-expand-lg>.container-sm,.navbar-expand-lg>.container-xl{flex-wrap:nowrap}.navbar-expand-lg .navbar-nav-scroll{overflow:visible}.navbar-expand-lg .navbar-collapse{display:flex!important;flex-basis:auto}.navbar-expand-lg .navbar-toggler{display:none}}@media (max-width:9.98px){.navbar-expand-xl>.container,.navbar-expand-xl>.container-fluid,.navbar-expand-xl>.container-lg,.navbar-expand-xl>.container-md,.navbar-expand-xl>.container-sm,.navbar-expand-xl>.container-xl{padding-left:0;padding-right:0}}@media (min-width:10px){.navbar-expand-xl{flex-flow:row nowrap;justify-content:flex-start}.navbar-expand-xl .navbar-nav{flex-direction:row}.navbar-expand-xl .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-xl .navbar-nav .nav-link{padding-left:.5rem;padding-right:.5rem}.navbar-expand-xl>.container,.navbar-expand-xl>.container-fluid,.navbar-expand-xl>.container-lg,.navbar-expand-xl>.container-md,.navbar-expand-xl>.container-sm,.navbar-expand-xl>.container-xl{flex-wrap:nowrap}.navbar-expand-xl .navbar-nav-scroll{overflow:visible}.navbar-expand-xl .navbar-collapse{display:flex!important;flex-basis:auto}.navbar-expand-xl .navbar-toggler{display:none}}.navbar-expand{flex-flow:row nowrap;justify-content:flex-start}.navbar-expand>.container,.navbar-expand>.container-fluid,.navbar-expand>.container-lg,.navbar-expand>.container-md,.navbar-expand>.container-sm,.navbar-expand>.container-xl{padding-left:0;padding-right:0}.navbar-expand .navbar-nav{flex-direction:row}.navbar-expand .navbar-nav .dropdown-menu{position:absolute}.navbar-expand .navbar-nav .nav-link{padding-left:.5rem;padding-right:.5rem}.navbar-expand>.container,.navbar-expand>.container-fluid,.navbar-expand>.container-lg,.navbar-expand>.container-md,.navbar-expand>.container-sm,.navbar-expand>.container-xl{flex-wrap:nowrap}.navbar-expand .navbar-nav-scroll{overflow:visible}.navbar-expand .navbar-collapse{display:flex!important;flex-basis:auto}.navbar-expand .navbar-toggler{display:none}.navbar-light .navbar-brand,.navbar-light .navbar-brand:focus,.navbar-light .navbar-brand:hover{color:rgba(0,0,0,.9)}.navbar-light .navbar-nav .nav-link{color:rgba(0,0,0,.5)}.navbar-light .navbar-nav .nav-link:focus,.navbar-light .navbar-nav .nav-link:hover{color:rgba(0,0,0,.7)}.navbar-light .navbar-nav .nav-link.disabled{color:rgba(0,0,0,.3)}.navbar-light .navbar-nav .active>.nav-link,.navbar-light .navbar-nav .nav-link.active,.navbar-light .navbar-nav .nav-link.show,.navbar-light .navbar-nav .show>.nav-link{color:rgba(0,0,0,.9)}.navbar-light .navbar-toggler{border-color:rgba(0,0,0,.1);color:rgba(0,0,0,.5)}.navbar-light .navbar-toggler-icon{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='30' height='30'%3E%3Cpath stroke='rgba(0, 0, 0, 0.5)' stroke-linecap='round' stroke-miterlimit='10' stroke-width='2' d='M4 7h22M4 15h22M4 23h22'/%3E%3C/svg%3E")}.navbar-light .navbar-text{color:rgba(0,0,0,.5)}.navbar-light .navbar-text a,.navbar-light .navbar-text a:focus,.navbar-light .navbar-text a:hover{color:rgba(0,0,0,.9)}.navbar-dark .navbar-brand,.navbar-dark .navbar-brand:focus,.navbar-dark .navbar-brand:hover{color:#fff}.navbar-dark .navbar-nav .nav-link{color:hsla(0,0%,100%,.5)}.navbar-dark .navbar-nav .nav-link:focus,.navbar-dark .navbar-nav .nav-link:hover{color:hsla(0,0%,100%,.75)}.navbar-dark .navbar-nav .nav-link.disabled{color:hsla(0,0%,100%,.25)}.navbar-dark .navbar-nav .active>.nav-link,.navbar-dark .navbar-nav .nav-link.active,.navbar-dark .navbar-nav .nav-link.show,.navbar-dark .navbar-nav .show>.nav-link{color:#fff}.navbar-dark .navbar-toggler{border-color:hsla(0,0%,100%,.1);color:hsla(0,0%,100%,.5)}.navbar-dark .navbar-toggler-icon{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='30' height='30'%3E%3Cpath stroke='rgba(255, 255, 255, 0.5)' stroke-linecap='round' stroke-miterlimit='10' stroke-width='2' d='M4 7h22M4 15h22M4 23h22'/%3E%3C/svg%3E")}.navbar-dark .navbar-text{color:hsla(0,0%,100%,.5)}.navbar-dark .navbar-text a,.navbar-dark .navbar-text a:focus,.navbar-dark .navbar-text a:hover{color:#fff}.card{word-wrap:break-word;background-clip:border-box;background-color:#fff;border:1px solid rgba(0,0,0,.125);border-radius:.25rem;display:flex;flex-direction:column;min-width:0;position:relative}.card>hr{margin-left:0;margin-right:0}.card>.list-group{border-bottom:inherit;border-top:inherit}.card>.list-group:first-child{border-top-left-radius:calc(.25rem - 1px);border-top-right-radius:calc(.25rem - 1px);border-top-width:0}.card>.list-group:last-child{border-bottom-left-radius:calc(.25rem - 1px);border-bottom-right-radius:calc(.25rem - 1px);border-bottom-width:0}.card>.card-header+.list-group,.card>.list-group+.card-footer{border-top:0}.card-body{flex:1 1 auto;min-height:1px;padding:1.25rem}.card-title{margin-bottom:.75rem}.card-subtitle{margin-top:-.375rem}.card-subtitle,.card-text:last-child{margin-bottom:0}.card-link:hover{text-decoration:none}.card-link+.card-link{margin-left:1.25rem}.card-header{background-color:#fff;border-bottom:1px solid rgba(0,0,0,.125);margin-bottom:0;padding:.75rem 1.25rem}.card-header:first-child{border-radius:calc(.25rem - 1px) calc(.25rem - 1px) 0 0}.card-footer{background-color:#fff;border-top:1px solid rgba(0,0,0,.125);padding:.75rem 1.25rem}.card-footer:last-child{border-radius:0 0 calc(.25rem - 1px) calc(.25rem - 1px)}.card-header-tabs{border-bottom:0;margin-bottom:-.75rem}.card-header-pills,.card-header-tabs{margin-left:-.625rem;margin-right:-.625rem}.card-img-overlay{border-radius:calc(.25rem - 1px);bottom:0;left:0;padding:1.25rem;position:absolute;right:0;top:0}.card-img,.card-img-bottom,.card-img-top{flex-shrink:0;width:100%}.card-img,.card-img-top{border-top-left-radius:calc(.25rem - 1px);border-top-right-radius:calc(.25rem - 1px)}.card-img,.card-img-bottom{border-bottom-left-radius:calc(.25rem - 1px);border-bottom-right-radius:calc(.25rem - 1px)}.card-deck .card{margin-bottom:15px}@media (min-width:2px){.card-deck{display:flex;flex-flow:row wrap;margin-left:-15px;margin-right:-15px}.card-deck .card{flex:1 0 0%;margin-bottom:0;margin-left:15px;margin-right:15px}}.card-group>.card{margin-bottom:15px}@media (min-width:2px){.card-group{display:flex;flex-flow:row wrap}.card-group>.card{flex:1 0 0%;margin-bottom:0}.card-group>.card+.card{border-left:0;margin-left:0}.card-group>.card:not(:last-child){border-bottom-right-radius:0;border-top-right-radius:0}.card-group>.card:not(:last-child) .card-header,.card-group>.card:not(:last-child) .card-img-top{border-top-right-radius:0}.card-group>.card:not(:last-child) .card-footer,.card-group>.card:not(:last-child) .card-img-bottom{border-bottom-right-radius:0}.card-group>.card:not(:first-child){border-bottom-left-radius:0;border-top-left-radius:0}.card-group>.card:not(:first-child) .card-header,.card-group>.card:not(:first-child) .card-img-top{border-top-left-radius:0}.card-group>.card:not(:first-child) .card-footer,.card-group>.card:not(:first-child) .card-img-bottom{border-bottom-left-radius:0}}.card-columns .card{margin-bottom:.75rem}@media (min-width:2px){.card-columns{-moz-column-count:3;column-count:3;-moz-column-gap:1.25rem;column-gap:1.25rem;orphans:1;widows:1}.card-columns .card{display:inline-block;width:100%}}.accordion{overflow-anchor:none}.accordion>.card{overflow:hidden}.accordion>.card:not(:last-of-type){border-bottom:0;border-bottom-left-radius:0;border-bottom-right-radius:0}.accordion>.card:not(:first-of-type){border-top-left-radius:0;border-top-right-radius:0}.accordion>.card>.card-header{border-radius:0;margin-bottom:-1px}.breadcrumb{background-color:#e9ecef;border-radius:.25rem;display:flex;flex-wrap:wrap;list-style:none;margin-bottom:1rem;padding:.75rem 1rem}.breadcrumb-item+.breadcrumb-item{padding-left:.5rem}.breadcrumb-item+.breadcrumb-item:before{color:#6c757d;content:"/";float:left;padding-right:.5rem}.breadcrumb-item+.breadcrumb-item:hover:before{text-decoration:underline;text-decoration:none}.breadcrumb-item.active{color:#6c757d}.pagination{border-radius:.25rem;display:flex;list-style:none;padding-left:0}.page-link{background-color:#fff;border:1px solid #dee2e6;color:#7746ec;display:block;line-height:1.25;margin-left:-1px;padding:.5rem .75rem;position:relative}.page-link:hover{background-color:#e9ecef;border-color:#dee2e6;color:#4d15d0;text-decoration:none;z-index:2}.page-link:focus{box-shadow:0 0 0 .2rem rgba(119,70,236,.25);outline:0;z-index:3}.page-item:first-child .page-link{border-bottom-left-radius:.25rem;border-top-left-radius:.25rem;margin-left:0}.page-item:last-child .page-link{border-bottom-right-radius:.25rem;border-top-right-radius:.25rem}.page-item.active .page-link{background-color:#7746ec;border-color:#7746ec;color:#fff;z-index:3}.page-item.disabled .page-link{background-color:#fff;border-color:#dee2e6;color:#6c757d;cursor:auto;pointer-events:none}.pagination-lg .page-link{font-size:1.1875rem;line-height:1.5;padding:.75rem 1.5rem}.pagination-lg .page-item:first-child .page-link{border-bottom-left-radius:.3rem;border-top-left-radius:.3rem}.pagination-lg .page-item:last-child .page-link{border-bottom-right-radius:.3rem;border-top-right-radius:.3rem}.pagination-sm .page-link{font-size:.83125rem;line-height:1.5;padding:.25rem .5rem}.pagination-sm .page-item:first-child .page-link{border-bottom-left-radius:.2rem;border-top-left-radius:.2rem}.pagination-sm .page-item:last-child .page-link{border-bottom-right-radius:.2rem;border-top-right-radius:.2rem}.badge{border-radius:.25rem;display:inline-block;font-size:.95rem;font-weight:700;line-height:1;padding:.25em .4em;text-align:center;transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;vertical-align:baseline;white-space:nowrap}@media (prefers-reduced-motion:reduce){.badge{transition:none}}a.badge:focus,a.badge:hover{text-decoration:none}.badge:empty{display:none}.btn .badge{position:relative;top:-1px}.badge-pill{border-radius:10rem;padding-left:.6em;padding-right:.6em}.badge-primary{background-color:#7746ec;color:#fff}a.badge-primary:focus,a.badge-primary:hover{background-color:#5518e7;color:#fff}a.badge-primary.focus,a.badge-primary:focus{box-shadow:0 0 0 .2rem rgba(119,70,236,.5);outline:0}.badge-secondary{background-color:#dae1e7;color:#212529}a.badge-secondary:focus,a.badge-secondary:hover{background-color:#bbc8d3;color:#212529}a.badge-secondary.focus,a.badge-secondary:focus{box-shadow:0 0 0 .2rem rgba(218,225,231,.5);outline:0}.badge-success{background-color:#51d88a;color:#212529}a.badge-success:focus,a.badge-success:hover{background-color:#2dc96f;color:#212529}a.badge-success.focus,a.badge-success:focus{box-shadow:0 0 0 .2rem rgba(81,216,138,.5);outline:0}.badge-info{background-color:#bcdefa;color:#212529}a.badge-info:focus,a.badge-info:hover{background-color:#8dc7f6;color:#212529}a.badge-info.focus,a.badge-info:focus{box-shadow:0 0 0 .2rem rgba(188,222,250,.5);outline:0}.badge-warning{background-color:#ffa260;color:#212529}a.badge-warning:focus,a.badge-warning:hover{background-color:#ff842d;color:#212529}a.badge-warning.focus,a.badge-warning:focus{box-shadow:0 0 0 .2rem rgba(255,162,96,.5);outline:0}.badge-danger{background-color:#ef5753;color:#fff}a.badge-danger:focus,a.badge-danger:hover{background-color:#eb2924;color:#fff}a.badge-danger.focus,a.badge-danger:focus{box-shadow:0 0 0 .2rem rgba(239,87,83,.5);outline:0}.badge-light{background-color:#f8f9fa;color:#212529}a.badge-light:focus,a.badge-light:hover{background-color:#dae0e5;color:#212529}a.badge-light.focus,a.badge-light:focus{box-shadow:0 0 0 .2rem rgba(248,249,250,.5);outline:0}.badge-dark{background-color:#343a40;color:#fff}a.badge-dark:focus,a.badge-dark:hover{background-color:#1d2124;color:#fff}a.badge-dark.focus,a.badge-dark:focus{box-shadow:0 0 0 .2rem rgba(52,58,64,.5);outline:0}.jumbotron{background-color:#e9ecef;border-radius:.3rem;margin-bottom:2rem;padding:2rem 1rem}@media (min-width:2px){.jumbotron{padding:4rem 2rem}}.jumbotron-fluid{border-radius:0;padding-left:0;padding-right:0}.alert{border:1px solid transparent;border-radius:.25rem;margin-bottom:1rem;padding:.75rem 1.25rem;position:relative}.alert-heading{color:inherit}.alert-link{font-weight:700}.alert-dismissible{padding-right:3.925rem}.alert-dismissible .close{color:inherit;padding:.75rem 1.25rem;position:absolute;right:0;top:0;z-index:2}.alert-primary{background-color:#e4dafb;border-color:#d9cbfa;color:#3e247b}.alert-primary hr{border-top-color:#c8b4f8}.alert-primary .alert-link{color:#2a1854}.alert-secondary{background-color:#f8f9fa;border-color:#f5f7f8;color:#717578}.alert-secondary hr{border-top-color:#e6ebee}.alert-secondary .alert-link{color:#585b5e}.alert-success{background-color:#dcf7e8;border-color:#cef4de;color:#2a7048}.alert-success hr{border-top-color:#b9efd0}.alert-success .alert-link{color:#1c4b30}.alert-info{background-color:#f2f8fe;border-color:#ecf6fe;color:#627382}.alert-info hr{border-top-color:#d4ebfd}.alert-info .alert-link{color:#4c5965}.alert-warning{background-color:#ffecdf;border-color:#ffe5d2;color:#855432}.alert-warning hr{border-top-color:#ffd6b9}.alert-warning .alert-link{color:#603d24}.alert-danger{background-color:#fcdddd;border-color:#fbd0cf;color:#7c2d2b}.alert-danger hr{border-top-color:#f9b9b7}.alert-danger .alert-link{color:#561f1e}.alert-light{background-color:#fefefe;border-color:#fdfdfe;color:#818182}.alert-light hr{border-top-color:#ececf6}.alert-light .alert-link{color:#686868}.alert-dark{background-color:#d6d8d9;border-color:#c6c8ca;color:#1b1e21}.alert-dark hr{border-top-color:#b9bbbe}.alert-dark .alert-link{color:#040505}@keyframes progress-bar-stripes{0%{background-position:1rem 0}to{background-position:0 0}}.progress{background-color:#e9ecef;border-radius:.25rem;font-size:.7125rem;height:1rem;line-height:0}.progress,.progress-bar{display:flex;overflow:hidden}.progress-bar{background-color:#7746ec;color:#fff;flex-direction:column;justify-content:center;text-align:center;transition:width .6s ease;white-space:nowrap}@media (prefers-reduced-motion:reduce){.progress-bar{transition:none}}.progress-bar-striped{background-image:linear-gradient(45deg,hsla(0,0%,100%,.15) 25%,transparent 0,transparent 50%,hsla(0,0%,100%,.15) 0,hsla(0,0%,100%,.15) 75%,transparent 0,transparent);background-size:1rem 1rem}.progress-bar-animated{animation:progress-bar-stripes 1s linear infinite}@media (prefers-reduced-motion:reduce){.progress-bar-animated{animation:none}}.media{align-items:flex-start;display:flex}.media-body{flex:1}.list-group{border-radius:.25rem;display:flex;flex-direction:column;margin-bottom:0;padding-left:0}.list-group-item-action{color:#495057;text-align:inherit;width:100%}.list-group-item-action:focus,.list-group-item-action:hover{background-color:#f8f9fa;color:#495057;text-decoration:none;z-index:1}.list-group-item-action:active{background-color:#e9ecef;color:#212529}.list-group-item{background-color:#fff;border:1px solid rgba(0,0,0,.125);display:block;padding:.75rem 1.25rem;position:relative}.list-group-item:first-child{border-top-left-radius:inherit;border-top-right-radius:inherit}.list-group-item:last-child{border-bottom-left-radius:inherit;border-bottom-right-radius:inherit}.list-group-item.disabled,.list-group-item:disabled{background-color:#fff;color:#6c757d;pointer-events:none}.list-group-item.active{background-color:#7746ec;border-color:#7746ec;color:#fff;z-index:2}.list-group-item+.list-group-item{border-top-width:0}.list-group-item+.list-group-item.active{border-top-width:1px;margin-top:-1px}.list-group-horizontal{flex-direction:row}.list-group-horizontal>.list-group-item:first-child{border-bottom-left-radius:.25rem;border-top-right-radius:0}.list-group-horizontal>.list-group-item:last-child{border-bottom-left-radius:0;border-top-right-radius:.25rem}.list-group-horizontal>.list-group-item.active{margin-top:0}.list-group-horizontal>.list-group-item+.list-group-item{border-left-width:0;border-top-width:1px}.list-group-horizontal>.list-group-item+.list-group-item.active{border-left-width:1px;margin-left:-1px}@media (min-width:2px){.list-group-horizontal-sm{flex-direction:row}.list-group-horizontal-sm>.list-group-item:first-child{border-bottom-left-radius:.25rem;border-top-right-radius:0}.list-group-horizontal-sm>.list-group-item:last-child{border-bottom-left-radius:0;border-top-right-radius:.25rem}.list-group-horizontal-sm>.list-group-item.active{margin-top:0}.list-group-horizontal-sm>.list-group-item+.list-group-item{border-left-width:0;border-top-width:1px}.list-group-horizontal-sm>.list-group-item+.list-group-item.active{border-left-width:1px;margin-left:-1px}}@media (min-width:8px){.list-group-horizontal-md{flex-direction:row}.list-group-horizontal-md>.list-group-item:first-child{border-bottom-left-radius:.25rem;border-top-right-radius:0}.list-group-horizontal-md>.list-group-item:last-child{border-bottom-left-radius:0;border-top-right-radius:.25rem}.list-group-horizontal-md>.list-group-item.active{margin-top:0}.list-group-horizontal-md>.list-group-item+.list-group-item{border-left-width:0;border-top-width:1px}.list-group-horizontal-md>.list-group-item+.list-group-item.active{border-left-width:1px;margin-left:-1px}}@media (min-width:9px){.list-group-horizontal-lg{flex-direction:row}.list-group-horizontal-lg>.list-group-item:first-child{border-bottom-left-radius:.25rem;border-top-right-radius:0}.list-group-horizontal-lg>.list-group-item:last-child{border-bottom-left-radius:0;border-top-right-radius:.25rem}.list-group-horizontal-lg>.list-group-item.active{margin-top:0}.list-group-horizontal-lg>.list-group-item+.list-group-item{border-left-width:0;border-top-width:1px}.list-group-horizontal-lg>.list-group-item+.list-group-item.active{border-left-width:1px;margin-left:-1px}}@media (min-width:10px){.list-group-horizontal-xl{flex-direction:row}.list-group-horizontal-xl>.list-group-item:first-child{border-bottom-left-radius:.25rem;border-top-right-radius:0}.list-group-horizontal-xl>.list-group-item:last-child{border-bottom-left-radius:0;border-top-right-radius:.25rem}.list-group-horizontal-xl>.list-group-item.active{margin-top:0}.list-group-horizontal-xl>.list-group-item+.list-group-item{border-left-width:0;border-top-width:1px}.list-group-horizontal-xl>.list-group-item+.list-group-item.active{border-left-width:1px;margin-left:-1px}}.list-group-flush{border-radius:0}.list-group-flush>.list-group-item{border-width:0 0 1px}.list-group-flush>.list-group-item:last-child{border-bottom-width:0}.list-group-item-primary{background-color:#d9cbfa;color:#3e247b}.list-group-item-primary.list-group-item-action:focus,.list-group-item-primary.list-group-item-action:hover{background-color:#c8b4f8;color:#3e247b}.list-group-item-primary.list-group-item-action.active{background-color:#3e247b;border-color:#3e247b;color:#fff}.list-group-item-secondary{background-color:#f5f7f8;color:#717578}.list-group-item-secondary.list-group-item-action:focus,.list-group-item-secondary.list-group-item-action:hover{background-color:#e6ebee;color:#717578}.list-group-item-secondary.list-group-item-action.active{background-color:#717578;border-color:#717578;color:#fff}.list-group-item-success{background-color:#cef4de;color:#2a7048}.list-group-item-success.list-group-item-action:focus,.list-group-item-success.list-group-item-action:hover{background-color:#b9efd0;color:#2a7048}.list-group-item-success.list-group-item-action.active{background-color:#2a7048;border-color:#2a7048;color:#fff}.list-group-item-info{background-color:#ecf6fe;color:#627382}.list-group-item-info.list-group-item-action:focus,.list-group-item-info.list-group-item-action:hover{background-color:#d4ebfd;color:#627382}.list-group-item-info.list-group-item-action.active{background-color:#627382;border-color:#627382;color:#fff}.list-group-item-warning{background-color:#ffe5d2;color:#855432}.list-group-item-warning.list-group-item-action:focus,.list-group-item-warning.list-group-item-action:hover{background-color:#ffd6b9;color:#855432}.list-group-item-warning.list-group-item-action.active{background-color:#855432;border-color:#855432;color:#fff}.list-group-item-danger{background-color:#fbd0cf;color:#7c2d2b}.list-group-item-danger.list-group-item-action:focus,.list-group-item-danger.list-group-item-action:hover{background-color:#f9b9b7;color:#7c2d2b}.list-group-item-danger.list-group-item-action.active{background-color:#7c2d2b;border-color:#7c2d2b;color:#fff}.list-group-item-light{background-color:#fdfdfe;color:#818182}.list-group-item-light.list-group-item-action:focus,.list-group-item-light.list-group-item-action:hover{background-color:#ececf6;color:#818182}.list-group-item-light.list-group-item-action.active{background-color:#818182;border-color:#818182;color:#fff}.list-group-item-dark{background-color:#c6c8ca;color:#1b1e21}.list-group-item-dark.list-group-item-action:focus,.list-group-item-dark.list-group-item-action:hover{background-color:#b9bbbe;color:#1b1e21}.list-group-item-dark.list-group-item-action.active{background-color:#1b1e21;border-color:#1b1e21;color:#fff}.close{color:#000;float:right;font-size:1.425rem;font-weight:700;line-height:1;opacity:.5;text-shadow:0 1px 0 #fff}.close:hover{color:#000;text-decoration:none}.close:not(:disabled):not(.disabled):focus,.close:not(:disabled):not(.disabled):hover{opacity:.75}button.close{background-color:transparent;border:0;padding:0}a.close.disabled{pointer-events:none}.toast{background-clip:padding-box;background-color:hsla(0,0%,100%,.85);border:1px solid rgba(0,0,0,.1);border-radius:.25rem;box-shadow:0 .25rem .75rem rgba(0,0,0,.1);flex-basis:350px;font-size:.875rem;max-width:350px;opacity:0}.toast:not(:last-child){margin-bottom:.75rem}.toast.showing{opacity:1}.toast.show{display:block;opacity:1}.toast.hide{display:none}.toast-header{align-items:center;background-clip:padding-box;background-color:hsla(0,0%,100%,.85);border-bottom:1px solid rgba(0,0,0,.05);border-top-left-radius:calc(.25rem - 1px);border-top-right-radius:calc(.25rem - 1px);color:#6c757d;display:flex;padding:.25rem .75rem}.toast-body{padding:.75rem}.modal-open{overflow:hidden}.modal-open .modal{overflow-x:hidden;overflow-y:auto}.modal{display:none;height:100%;left:0;outline:0;overflow:hidden;position:fixed;top:0;width:100%;z-index:1050}.modal-dialog{margin:.5rem;pointer-events:none;position:relative;width:auto}.modal.fade .modal-dialog{transform:translateY(-50px);transition:transform .3s ease-out}@media (prefers-reduced-motion:reduce){.modal.fade .modal-dialog{transition:none}}.modal.show .modal-dialog{transform:none}.modal.modal-static .modal-dialog{transform:scale(1.02)}.modal-dialog-scrollable{display:flex;max-height:calc(100% - 1rem)}.modal-dialog-scrollable .modal-content{max-height:calc(100vh - 1rem);overflow:hidden}.modal-dialog-scrollable .modal-footer,.modal-dialog-scrollable .modal-header{flex-shrink:0}.modal-dialog-scrollable .modal-body{overflow-y:auto}.modal-dialog-centered{align-items:center;display:flex;min-height:calc(100% - 1rem)}.modal-dialog-centered:before{content:"";display:block;height:calc(100vh - 1rem);height:-moz-min-content;height:min-content}.modal-dialog-centered.modal-dialog-scrollable{flex-direction:column;height:100%;justify-content:center}.modal-dialog-centered.modal-dialog-scrollable .modal-content{max-height:none}.modal-dialog-centered.modal-dialog-scrollable:before{content:none}.modal-content{background-clip:padding-box;background-color:#fff;border:1px solid rgba(0,0,0,.2);border-radius:.3rem;display:flex;flex-direction:column;outline:0;pointer-events:auto;position:relative;width:100%}.modal-backdrop{background-color:#000;height:100vh;left:0;position:fixed;top:0;width:100vw;z-index:1040}.modal-backdrop.fade{opacity:0}.modal-backdrop.show{opacity:.5}.modal-header{align-items:flex-start;border-bottom:1px solid #efefef;border-top-left-radius:calc(.3rem - 1px);border-top-right-radius:calc(.3rem - 1px);display:flex;justify-content:space-between;padding:1rem}.modal-header .close{margin:-1rem -1rem -1rem auto;padding:1rem}.modal-title{line-height:1.5;margin-bottom:0}.modal-body{flex:1 1 auto;padding:1rem;position:relative}.modal-footer{align-items:center;border-bottom-left-radius:calc(.3rem - 1px);border-bottom-right-radius:calc(.3rem - 1px);border-top:1px solid #efefef;display:flex;flex-wrap:wrap;justify-content:flex-end;padding:.75rem}.modal-footer>*{margin:.25rem}.modal-scrollbar-measure{height:50px;overflow:scroll;position:absolute;top:-9999px;width:50px}@media (min-width:2px){.modal-dialog{margin:1.75rem auto;max-width:500px}.modal-dialog-scrollable{max-height:calc(100% - 3.5rem)}.modal-dialog-scrollable .modal-content{max-height:calc(100vh - 3.5rem)}.modal-dialog-centered{min-height:calc(100% - 3.5rem)}.modal-dialog-centered:before{height:calc(100vh - 3.5rem);height:-moz-min-content;height:min-content}.modal-sm{max-width:300px}}@media (min-width:9px){.modal-lg,.modal-xl{max-width:800px}}@media (min-width:10px){.modal-xl{max-width:1140px}}.tooltip{word-wrap:break-word;display:block;font-family:Nunito,sans-serif;font-size:.83125rem;font-style:normal;font-weight:400;letter-spacing:normal;line-break:auto;line-height:1.5;margin:0;opacity:0;position:absolute;text-align:left;text-align:start;text-decoration:none;text-shadow:none;text-transform:none;white-space:normal;word-break:normal;word-spacing:normal;z-index:1070}.tooltip.show{opacity:.9}.tooltip .arrow{display:block;height:.4rem;position:absolute;width:.8rem}.tooltip .arrow:before{border-color:transparent;border-style:solid;content:"";position:absolute}.bs-tooltip-auto[x-placement^=top],.bs-tooltip-top{padding:.4rem 0}.bs-tooltip-auto[x-placement^=top] .arrow,.bs-tooltip-top .arrow{bottom:0}.bs-tooltip-auto[x-placement^=top] .arrow:before,.bs-tooltip-top .arrow:before{border-top-color:#000;border-width:.4rem .4rem 0;top:0}.bs-tooltip-auto[x-placement^=right],.bs-tooltip-right{padding:0 .4rem}.bs-tooltip-auto[x-placement^=right] .arrow,.bs-tooltip-right .arrow{height:.8rem;left:0;width:.4rem}.bs-tooltip-auto[x-placement^=right] .arrow:before,.bs-tooltip-right .arrow:before{border-right-color:#000;border-width:.4rem .4rem .4rem 0;right:0}.bs-tooltip-auto[x-placement^=bottom],.bs-tooltip-bottom{padding:.4rem 0}.bs-tooltip-auto[x-placement^=bottom] .arrow,.bs-tooltip-bottom .arrow{top:0}.bs-tooltip-auto[x-placement^=bottom] .arrow:before,.bs-tooltip-bottom .arrow:before{border-bottom-color:#000;border-width:0 .4rem .4rem;bottom:0}.bs-tooltip-auto[x-placement^=left],.bs-tooltip-left{padding:0 .4rem}.bs-tooltip-auto[x-placement^=left] .arrow,.bs-tooltip-left .arrow{height:.8rem;right:0;width:.4rem}.bs-tooltip-auto[x-placement^=left] .arrow:before,.bs-tooltip-left .arrow:before{border-left-color:#000;border-width:.4rem 0 .4rem .4rem;left:0}.tooltip-inner{background-color:#000;border-radius:.25rem;color:#fff;max-width:200px;padding:.25rem .5rem;text-align:center}.popover{word-wrap:break-word;background-clip:padding-box;background-color:#fff;border:1px solid rgba(0,0,0,.2);border-radius:.3rem;font-family:Nunito,sans-serif;font-size:.83125rem;font-style:normal;font-weight:400;left:0;letter-spacing:normal;line-break:auto;line-height:1.5;max-width:276px;text-align:left;text-align:start;text-decoration:none;text-shadow:none;text-transform:none;top:0;white-space:normal;word-break:normal;word-spacing:normal;z-index:1060}.popover,.popover .arrow{display:block;position:absolute}.popover .arrow{height:.5rem;margin:0 .3rem;width:1rem}.popover .arrow:after,.popover .arrow:before{border-color:transparent;border-style:solid;content:"";display:block;position:absolute}.bs-popover-auto[x-placement^=top],.bs-popover-top{margin-bottom:.5rem}.bs-popover-auto[x-placement^=top]>.arrow,.bs-popover-top>.arrow{bottom:calc(-.5rem - 1px)}.bs-popover-auto[x-placement^=top]>.arrow:before,.bs-popover-top>.arrow:before{border-top-color:rgba(0,0,0,.25);border-width:.5rem .5rem 0;bottom:0}.bs-popover-auto[x-placement^=top]>.arrow:after,.bs-popover-top>.arrow:after{border-top-color:#fff;border-width:.5rem .5rem 0;bottom:1px}.bs-popover-auto[x-placement^=right],.bs-popover-right{margin-left:.5rem}.bs-popover-auto[x-placement^=right]>.arrow,.bs-popover-right>.arrow{height:1rem;left:calc(-.5rem - 1px);margin:.3rem 0;width:.5rem}.bs-popover-auto[x-placement^=right]>.arrow:before,.bs-popover-right>.arrow:before{border-right-color:rgba(0,0,0,.25);border-width:.5rem .5rem .5rem 0;left:0}.bs-popover-auto[x-placement^=right]>.arrow:after,.bs-popover-right>.arrow:after{border-right-color:#fff;border-width:.5rem .5rem .5rem 0;left:1px}.bs-popover-auto[x-placement^=bottom],.bs-popover-bottom{margin-top:.5rem}.bs-popover-auto[x-placement^=bottom]>.arrow,.bs-popover-bottom>.arrow{top:calc(-.5rem - 1px)}.bs-popover-auto[x-placement^=bottom]>.arrow:before,.bs-popover-bottom>.arrow:before{border-bottom-color:rgba(0,0,0,.25);border-width:0 .5rem .5rem;top:0}.bs-popover-auto[x-placement^=bottom]>.arrow:after,.bs-popover-bottom>.arrow:after{border-bottom-color:#fff;border-width:0 .5rem .5rem;top:1px}.bs-popover-auto[x-placement^=bottom] .popover-header:before,.bs-popover-bottom .popover-header:before{border-bottom:1px solid #f7f7f7;content:"";display:block;left:50%;margin-left:-.5rem;position:absolute;top:0;width:1rem}.bs-popover-auto[x-placement^=left],.bs-popover-left{margin-right:.5rem}.bs-popover-auto[x-placement^=left]>.arrow,.bs-popover-left>.arrow{height:1rem;margin:.3rem 0;right:calc(-.5rem - 1px);width:.5rem}.bs-popover-auto[x-placement^=left]>.arrow:before,.bs-popover-left>.arrow:before{border-left-color:rgba(0,0,0,.25);border-width:.5rem 0 .5rem .5rem;right:0}.bs-popover-auto[x-placement^=left]>.arrow:after,.bs-popover-left>.arrow:after{border-left-color:#fff;border-width:.5rem 0 .5rem .5rem;right:1px}.popover-header{background-color:#f7f7f7;border-bottom:1px solid #ebebeb;border-top-left-radius:calc(.3rem - 1px);border-top-right-radius:calc(.3rem - 1px);font-size:.95rem;margin-bottom:0;padding:.5rem .75rem}.popover-header:empty{display:none}.popover-body{color:#212529;padding:.5rem .75rem}.carousel{position:relative}.carousel.pointer-event{touch-action:pan-y}.carousel-inner{overflow:hidden;position:relative;width:100%}.carousel-inner:after{clear:both;content:"";display:block}.carousel-item{-webkit-backface-visibility:hidden;backface-visibility:hidden;display:none;float:left;margin-right:-100%;position:relative;transition:transform .6s ease-in-out;width:100%}@media (prefers-reduced-motion:reduce){.carousel-item{transition:none}}.carousel-item-next,.carousel-item-prev,.carousel-item.active{display:block}.active.carousel-item-right,.carousel-item-next:not(.carousel-item-left){transform:translateX(100%)}.active.carousel-item-left,.carousel-item-prev:not(.carousel-item-right){transform:translateX(-100%)}.carousel-fade .carousel-item{opacity:0;transform:none;transition-property:opacity}.carousel-fade .carousel-item-next.carousel-item-left,.carousel-fade .carousel-item-prev.carousel-item-right,.carousel-fade .carousel-item.active{opacity:1;z-index:1}.carousel-fade .active.carousel-item-left,.carousel-fade .active.carousel-item-right{opacity:0;transition:opacity 0s .6s;z-index:0}@media (prefers-reduced-motion:reduce){.carousel-fade .active.carousel-item-left,.carousel-fade .active.carousel-item-right{transition:none}}.carousel-control-next,.carousel-control-prev{align-items:center;background:none;border:0;bottom:0;color:#fff;display:flex;justify-content:center;opacity:.5;padding:0;position:absolute;text-align:center;top:0;transition:opacity .15s ease;width:15%;z-index:1}@media (prefers-reduced-motion:reduce){.carousel-control-next,.carousel-control-prev{transition:none}}.carousel-control-next:focus,.carousel-control-next:hover,.carousel-control-prev:focus,.carousel-control-prev:hover{color:#fff;opacity:.9;outline:0;text-decoration:none}.carousel-control-prev{left:0}.carousel-control-next{right:0}.carousel-control-next-icon,.carousel-control-prev-icon{background:50%/100% 100% no-repeat;display:inline-block;height:20px;width:20px}.carousel-control-prev-icon{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='%23fff' width='8' height='8'%3E%3Cpath d='m5.25 0-4 4 4 4 1.5-1.5L4.25 4l2.5-2.5L5.25 0z'/%3E%3C/svg%3E")}.carousel-control-next-icon{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='%23fff' width='8' height='8'%3E%3Cpath d='m2.75 0-1.5 1.5L3.75 4l-2.5 2.5L2.75 8l4-4-4-4z'/%3E%3C/svg%3E")}.carousel-indicators{bottom:0;display:flex;justify-content:center;left:0;list-style:none;margin-left:15%;margin-right:15%;padding-left:0;position:absolute;right:0;z-index:15}.carousel-indicators li{background-clip:padding-box;background-color:#fff;border-bottom:10px solid transparent;border-top:10px solid transparent;box-sizing:content-box;cursor:pointer;flex:0 1 auto;height:3px;margin-left:3px;margin-right:3px;opacity:.5;text-indent:-999px;transition:opacity .6s ease;width:30px}@media (prefers-reduced-motion:reduce){.carousel-indicators li{transition:none}}.carousel-indicators .active{opacity:1}.carousel-caption{bottom:20px;color:#fff;left:15%;padding-bottom:20px;padding-top:20px;position:absolute;right:15%;text-align:center;z-index:10}@keyframes spinner-border{to{transform:rotate(1turn)}}.spinner-border{animation:spinner-border .75s linear infinite;border:.25em solid;border-radius:50%;border-right:.25em solid transparent;display:inline-block;height:2rem;vertical-align:-.125em;width:2rem}.spinner-border-sm{border-width:.2em;height:1rem;width:1rem}@keyframes spinner-grow{0%{transform:scale(0)}50%{opacity:1;transform:none}}.spinner-grow{animation:spinner-grow .75s linear infinite;background-color:currentcolor;border-radius:50%;display:inline-block;height:2rem;opacity:0;vertical-align:-.125em;width:2rem}.spinner-grow-sm{height:1rem;width:1rem}@media (prefers-reduced-motion:reduce){.spinner-border,.spinner-grow{animation-duration:1.5s}}.align-baseline{vertical-align:baseline!important}.align-top{vertical-align:top!important}.align-middle{vertical-align:middle!important}.align-bottom{vertical-align:bottom!important}.align-text-bottom{vertical-align:text-bottom!important}.align-text-top{vertical-align:text-top!important}.bg-primary{background-color:#7746ec!important}a.bg-primary:focus,a.bg-primary:hover,button.bg-primary:focus,button.bg-primary:hover{background-color:#5518e7!important}.bg-secondary{background-color:#dae1e7!important}a.bg-secondary:focus,a.bg-secondary:hover,button.bg-secondary:focus,button.bg-secondary:hover{background-color:#bbc8d3!important}.bg-success{background-color:#51d88a!important}a.bg-success:focus,a.bg-success:hover,button.bg-success:focus,button.bg-success:hover{background-color:#2dc96f!important}.bg-info{background-color:#bcdefa!important}a.bg-info:focus,a.bg-info:hover,button.bg-info:focus,button.bg-info:hover{background-color:#8dc7f6!important}.bg-warning{background-color:#ffa260!important}a.bg-warning:focus,a.bg-warning:hover,button.bg-warning:focus,button.bg-warning:hover{background-color:#ff842d!important}.bg-danger{background-color:#ef5753!important}a.bg-danger:focus,a.bg-danger:hover,button.bg-danger:focus,button.bg-danger:hover{background-color:#eb2924!important}.bg-light{background-color:#f8f9fa!important}a.bg-light:focus,a.bg-light:hover,button.bg-light:focus,button.bg-light:hover{background-color:#dae0e5!important}.bg-dark{background-color:#343a40!important}a.bg-dark:focus,a.bg-dark:hover,button.bg-dark:focus,button.bg-dark:hover{background-color:#1d2124!important}.bg-white{background-color:#fff!important}.bg-transparent{background-color:transparent!important}.border{border:1px solid #efefef!important}.border-top{border-top:1px solid #efefef!important}.border-right{border-right:1px solid #efefef!important}.border-bottom{border-bottom:1px solid #efefef!important}.border-left{border-left:1px solid #efefef!important}.border-0{border:0!important}.border-top-0{border-top:0!important}.border-right-0{border-right:0!important}.border-bottom-0{border-bottom:0!important}.border-left-0{border-left:0!important}.border-primary{border-color:#7746ec!important}.border-secondary{border-color:#dae1e7!important}.border-success{border-color:#51d88a!important}.border-info{border-color:#bcdefa!important}.border-warning{border-color:#ffa260!important}.border-danger{border-color:#ef5753!important}.border-light{border-color:#f8f9fa!important}.border-dark{border-color:#343a40!important}.border-white{border-color:#fff!important}.rounded-sm{border-radius:.2rem!important}.rounded{border-radius:.25rem!important}.rounded-top{border-top-left-radius:.25rem!important}.rounded-right,.rounded-top{border-top-right-radius:.25rem!important}.rounded-bottom,.rounded-right{border-bottom-right-radius:.25rem!important}.rounded-bottom,.rounded-left{border-bottom-left-radius:.25rem!important}.rounded-left{border-top-left-radius:.25rem!important}.rounded-lg{border-radius:.3rem!important}.rounded-circle{border-radius:50%!important}.rounded-pill{border-radius:50rem!important}.rounded-0{border-radius:0!important}.clearfix:after{clear:both;content:"";display:block}.d-none{display:none!important}.d-inline{display:inline!important}.d-inline-block{display:inline-block!important}.d-block{display:block!important}.d-table{display:table!important}.d-table-row{display:table-row!important}.d-table-cell{display:table-cell!important}.d-flex{display:flex!important}.d-inline-flex{display:inline-flex!important}@media (min-width:2px){.d-sm-none{display:none!important}.d-sm-inline{display:inline!important}.d-sm-inline-block{display:inline-block!important}.d-sm-block{display:block!important}.d-sm-table{display:table!important}.d-sm-table-row{display:table-row!important}.d-sm-table-cell{display:table-cell!important}.d-sm-flex{display:flex!important}.d-sm-inline-flex{display:inline-flex!important}}@media (min-width:8px){.d-md-none{display:none!important}.d-md-inline{display:inline!important}.d-md-inline-block{display:inline-block!important}.d-md-block{display:block!important}.d-md-table{display:table!important}.d-md-table-row{display:table-row!important}.d-md-table-cell{display:table-cell!important}.d-md-flex{display:flex!important}.d-md-inline-flex{display:inline-flex!important}}@media (min-width:9px){.d-lg-none{display:none!important}.d-lg-inline{display:inline!important}.d-lg-inline-block{display:inline-block!important}.d-lg-block{display:block!important}.d-lg-table{display:table!important}.d-lg-table-row{display:table-row!important}.d-lg-table-cell{display:table-cell!important}.d-lg-flex{display:flex!important}.d-lg-inline-flex{display:inline-flex!important}}@media (min-width:10px){.d-xl-none{display:none!important}.d-xl-inline{display:inline!important}.d-xl-inline-block{display:inline-block!important}.d-xl-block{display:block!important}.d-xl-table{display:table!important}.d-xl-table-row{display:table-row!important}.d-xl-table-cell{display:table-cell!important}.d-xl-flex{display:flex!important}.d-xl-inline-flex{display:inline-flex!important}}@media print{.d-print-none{display:none!important}.d-print-inline{display:inline!important}.d-print-inline-block{display:inline-block!important}.d-print-block{display:block!important}.d-print-table{display:table!important}.d-print-table-row{display:table-row!important}.d-print-table-cell{display:table-cell!important}.d-print-flex{display:flex!important}.d-print-inline-flex{display:inline-flex!important}}.embed-responsive{display:block;overflow:hidden;padding:0;position:relative;width:100%}.embed-responsive:before{content:"";display:block}.embed-responsive .embed-responsive-item,.embed-responsive embed,.embed-responsive iframe,.embed-responsive object,.embed-responsive video{border:0;bottom:0;height:100%;left:0;position:absolute;top:0;width:100%}.embed-responsive-21by9:before{padding-top:42.85714286%}.embed-responsive-16by9:before{padding-top:56.25%}.embed-responsive-4by3:before{padding-top:75%}.embed-responsive-1by1:before{padding-top:100%}.flex-row{flex-direction:row!important}.flex-column{flex-direction:column!important}.flex-row-reverse{flex-direction:row-reverse!important}.flex-column-reverse{flex-direction:column-reverse!important}.flex-wrap{flex-wrap:wrap!important}.flex-nowrap{flex-wrap:nowrap!important}.flex-wrap-reverse{flex-wrap:wrap-reverse!important}.flex-fill{flex:1 1 auto!important}.flex-grow-0{flex-grow:0!important}.flex-grow-1{flex-grow:1!important}.flex-shrink-0{flex-shrink:0!important}.flex-shrink-1{flex-shrink:1!important}.justify-content-start{justify-content:flex-start!important}.justify-content-end{justify-content:flex-end!important}.justify-content-center{justify-content:center!important}.justify-content-between{justify-content:space-between!important}.justify-content-around{justify-content:space-around!important}.align-items-start{align-items:flex-start!important}.align-items-end{align-items:flex-end!important}.align-items-center{align-items:center!important}.align-items-baseline{align-items:baseline!important}.align-items-stretch{align-items:stretch!important}.align-content-start{align-content:flex-start!important}.align-content-end{align-content:flex-end!important}.align-content-center{align-content:center!important}.align-content-between{align-content:space-between!important}.align-content-around{align-content:space-around!important}.align-content-stretch{align-content:stretch!important}.align-self-auto{align-self:auto!important}.align-self-start{align-self:flex-start!important}.align-self-end{align-self:flex-end!important}.align-self-center{align-self:center!important}.align-self-baseline{align-self:baseline!important}.align-self-stretch{align-self:stretch!important}@media (min-width:2px){.flex-sm-row{flex-direction:row!important}.flex-sm-column{flex-direction:column!important}.flex-sm-row-reverse{flex-direction:row-reverse!important}.flex-sm-column-reverse{flex-direction:column-reverse!important}.flex-sm-wrap{flex-wrap:wrap!important}.flex-sm-nowrap{flex-wrap:nowrap!important}.flex-sm-wrap-reverse{flex-wrap:wrap-reverse!important}.flex-sm-fill{flex:1 1 auto!important}.flex-sm-grow-0{flex-grow:0!important}.flex-sm-grow-1{flex-grow:1!important}.flex-sm-shrink-0{flex-shrink:0!important}.flex-sm-shrink-1{flex-shrink:1!important}.justify-content-sm-start{justify-content:flex-start!important}.justify-content-sm-end{justify-content:flex-end!important}.justify-content-sm-center{justify-content:center!important}.justify-content-sm-between{justify-content:space-between!important}.justify-content-sm-around{justify-content:space-around!important}.align-items-sm-start{align-items:flex-start!important}.align-items-sm-end{align-items:flex-end!important}.align-items-sm-center{align-items:center!important}.align-items-sm-baseline{align-items:baseline!important}.align-items-sm-stretch{align-items:stretch!important}.align-content-sm-start{align-content:flex-start!important}.align-content-sm-end{align-content:flex-end!important}.align-content-sm-center{align-content:center!important}.align-content-sm-between{align-content:space-between!important}.align-content-sm-around{align-content:space-around!important}.align-content-sm-stretch{align-content:stretch!important}.align-self-sm-auto{align-self:auto!important}.align-self-sm-start{align-self:flex-start!important}.align-self-sm-end{align-self:flex-end!important}.align-self-sm-center{align-self:center!important}.align-self-sm-baseline{align-self:baseline!important}.align-self-sm-stretch{align-self:stretch!important}}@media (min-width:8px){.flex-md-row{flex-direction:row!important}.flex-md-column{flex-direction:column!important}.flex-md-row-reverse{flex-direction:row-reverse!important}.flex-md-column-reverse{flex-direction:column-reverse!important}.flex-md-wrap{flex-wrap:wrap!important}.flex-md-nowrap{flex-wrap:nowrap!important}.flex-md-wrap-reverse{flex-wrap:wrap-reverse!important}.flex-md-fill{flex:1 1 auto!important}.flex-md-grow-0{flex-grow:0!important}.flex-md-grow-1{flex-grow:1!important}.flex-md-shrink-0{flex-shrink:0!important}.flex-md-shrink-1{flex-shrink:1!important}.justify-content-md-start{justify-content:flex-start!important}.justify-content-md-end{justify-content:flex-end!important}.justify-content-md-center{justify-content:center!important}.justify-content-md-between{justify-content:space-between!important}.justify-content-md-around{justify-content:space-around!important}.align-items-md-start{align-items:flex-start!important}.align-items-md-end{align-items:flex-end!important}.align-items-md-center{align-items:center!important}.align-items-md-baseline{align-items:baseline!important}.align-items-md-stretch{align-items:stretch!important}.align-content-md-start{align-content:flex-start!important}.align-content-md-end{align-content:flex-end!important}.align-content-md-center{align-content:center!important}.align-content-md-between{align-content:space-between!important}.align-content-md-around{align-content:space-around!important}.align-content-md-stretch{align-content:stretch!important}.align-self-md-auto{align-self:auto!important}.align-self-md-start{align-self:flex-start!important}.align-self-md-end{align-self:flex-end!important}.align-self-md-center{align-self:center!important}.align-self-md-baseline{align-self:baseline!important}.align-self-md-stretch{align-self:stretch!important}}@media (min-width:9px){.flex-lg-row{flex-direction:row!important}.flex-lg-column{flex-direction:column!important}.flex-lg-row-reverse{flex-direction:row-reverse!important}.flex-lg-column-reverse{flex-direction:column-reverse!important}.flex-lg-wrap{flex-wrap:wrap!important}.flex-lg-nowrap{flex-wrap:nowrap!important}.flex-lg-wrap-reverse{flex-wrap:wrap-reverse!important}.flex-lg-fill{flex:1 1 auto!important}.flex-lg-grow-0{flex-grow:0!important}.flex-lg-grow-1{flex-grow:1!important}.flex-lg-shrink-0{flex-shrink:0!important}.flex-lg-shrink-1{flex-shrink:1!important}.justify-content-lg-start{justify-content:flex-start!important}.justify-content-lg-end{justify-content:flex-end!important}.justify-content-lg-center{justify-content:center!important}.justify-content-lg-between{justify-content:space-between!important}.justify-content-lg-around{justify-content:space-around!important}.align-items-lg-start{align-items:flex-start!important}.align-items-lg-end{align-items:flex-end!important}.align-items-lg-center{align-items:center!important}.align-items-lg-baseline{align-items:baseline!important}.align-items-lg-stretch{align-items:stretch!important}.align-content-lg-start{align-content:flex-start!important}.align-content-lg-end{align-content:flex-end!important}.align-content-lg-center{align-content:center!important}.align-content-lg-between{align-content:space-between!important}.align-content-lg-around{align-content:space-around!important}.align-content-lg-stretch{align-content:stretch!important}.align-self-lg-auto{align-self:auto!important}.align-self-lg-start{align-self:flex-start!important}.align-self-lg-end{align-self:flex-end!important}.align-self-lg-center{align-self:center!important}.align-self-lg-baseline{align-self:baseline!important}.align-self-lg-stretch{align-self:stretch!important}}@media (min-width:10px){.flex-xl-row{flex-direction:row!important}.flex-xl-column{flex-direction:column!important}.flex-xl-row-reverse{flex-direction:row-reverse!important}.flex-xl-column-reverse{flex-direction:column-reverse!important}.flex-xl-wrap{flex-wrap:wrap!important}.flex-xl-nowrap{flex-wrap:nowrap!important}.flex-xl-wrap-reverse{flex-wrap:wrap-reverse!important}.flex-xl-fill{flex:1 1 auto!important}.flex-xl-grow-0{flex-grow:0!important}.flex-xl-grow-1{flex-grow:1!important}.flex-xl-shrink-0{flex-shrink:0!important}.flex-xl-shrink-1{flex-shrink:1!important}.justify-content-xl-start{justify-content:flex-start!important}.justify-content-xl-end{justify-content:flex-end!important}.justify-content-xl-center{justify-content:center!important}.justify-content-xl-between{justify-content:space-between!important}.justify-content-xl-around{justify-content:space-around!important}.align-items-xl-start{align-items:flex-start!important}.align-items-xl-end{align-items:flex-end!important}.align-items-xl-center{align-items:center!important}.align-items-xl-baseline{align-items:baseline!important}.align-items-xl-stretch{align-items:stretch!important}.align-content-xl-start{align-content:flex-start!important}.align-content-xl-end{align-content:flex-end!important}.align-content-xl-center{align-content:center!important}.align-content-xl-between{align-content:space-between!important}.align-content-xl-around{align-content:space-around!important}.align-content-xl-stretch{align-content:stretch!important}.align-self-xl-auto{align-self:auto!important}.align-self-xl-start{align-self:flex-start!important}.align-self-xl-end{align-self:flex-end!important}.align-self-xl-center{align-self:center!important}.align-self-xl-baseline{align-self:baseline!important}.align-self-xl-stretch{align-self:stretch!important}}.float-left{float:left!important}.float-right{float:right!important}.float-none{float:none!important}@media (min-width:2px){.float-sm-left{float:left!important}.float-sm-right{float:right!important}.float-sm-none{float:none!important}}@media (min-width:8px){.float-md-left{float:left!important}.float-md-right{float:right!important}.float-md-none{float:none!important}}@media (min-width:9px){.float-lg-left{float:left!important}.float-lg-right{float:right!important}.float-lg-none{float:none!important}}@media (min-width:10px){.float-xl-left{float:left!important}.float-xl-right{float:right!important}.float-xl-none{float:none!important}}.user-select-all{-webkit-user-select:all!important;-moz-user-select:all!important;user-select:all!important}.user-select-auto{-webkit-user-select:auto!important;-moz-user-select:auto!important;user-select:auto!important}.user-select-none{-webkit-user-select:none!important;-moz-user-select:none!important;user-select:none!important}.overflow-auto{overflow:auto!important}.overflow-hidden{overflow:hidden!important}.position-static{position:static!important}.position-relative{position:relative!important}.position-absolute{position:absolute!important}.position-fixed{position:fixed!important}.position-sticky{position:sticky!important}.fixed-top{top:0}.fixed-bottom,.fixed-top{left:0;position:fixed;right:0;z-index:1030}.fixed-bottom{bottom:0}@supports (position:sticky){.sticky-top{position:sticky;top:0;z-index:1020}}.sr-only{clip:rect(0,0,0,0);border:0;height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;white-space:nowrap;width:1px}.sr-only-focusable:active,.sr-only-focusable:focus{clip:auto;height:auto;overflow:visible;position:static;white-space:normal;width:auto}.shadow-sm{box-shadow:0 .125rem .25rem rgba(0,0,0,.075)!important}.shadow{box-shadow:0 .5rem 1rem rgba(0,0,0,.15)!important}.shadow-lg{box-shadow:0 1rem 3rem rgba(0,0,0,.175)!important}.shadow-none{box-shadow:none!important}.w-25{width:25%!important}.w-50{width:50%!important}.w-75{width:75%!important}.w-100{width:100%!important}.w-auto{width:auto!important}.h-25{height:25%!important}.h-50{height:50%!important}.h-75{height:75%!important}.h-100{height:100%!important}.h-auto{height:auto!important}.mw-100{max-width:100%!important}.mh-100{max-height:100%!important}.min-vw-100{min-width:100vw!important}.min-vh-100{min-height:100vh!important}.vw-100{width:100vw!important}.vh-100{height:100vh!important}.m-0{margin:0!important}.mt-0,.my-0{margin-top:0!important}.mr-0,.mx-0{margin-right:0!important}.mb-0,.my-0{margin-bottom:0!important}.ml-0,.mx-0{margin-left:0!important}.m-1{margin:.25rem!important}.mt-1,.my-1{margin-top:.25rem!important}.mr-1,.mx-1{margin-right:.25rem!important}.mb-1,.my-1{margin-bottom:.25rem!important}.ml-1,.mx-1{margin-left:.25rem!important}.m-2{margin:.5rem!important}.mt-2,.my-2{margin-top:.5rem!important}.mr-2,.mx-2{margin-right:.5rem!important}.mb-2,.my-2{margin-bottom:.5rem!important}.ml-2,.mx-2{margin-left:.5rem!important}.m-3{margin:1rem!important}.mt-3,.my-3{margin-top:1rem!important}.mr-3,.mx-3{margin-right:1rem!important}.mb-3,.my-3{margin-bottom:1rem!important}.ml-3,.mx-3{margin-left:1rem!important}.m-4{margin:1.5rem!important}.mt-4,.my-4{margin-top:1.5rem!important}.mr-4,.mx-4{margin-right:1.5rem!important}.mb-4,.my-4{margin-bottom:1.5rem!important}.ml-4,.mx-4{margin-left:1.5rem!important}.m-5{margin:3rem!important}.mt-5,.my-5{margin-top:3rem!important}.mr-5,.mx-5{margin-right:3rem!important}.mb-5,.my-5{margin-bottom:3rem!important}.ml-5,.mx-5{margin-left:3rem!important}.p-0{padding:0!important}.pt-0,.py-0{padding-top:0!important}.pr-0,.px-0{padding-right:0!important}.pb-0,.py-0{padding-bottom:0!important}.pl-0,.px-0{padding-left:0!important}.p-1{padding:.25rem!important}.pt-1,.py-1{padding-top:.25rem!important}.pr-1,.px-1{padding-right:.25rem!important}.pb-1,.py-1{padding-bottom:.25rem!important}.pl-1,.px-1{padding-left:.25rem!important}.p-2{padding:.5rem!important}.pt-2,.py-2{padding-top:.5rem!important}.pr-2,.px-2{padding-right:.5rem!important}.pb-2,.py-2{padding-bottom:.5rem!important}.pl-2,.px-2{padding-left:.5rem!important}.p-3{padding:1rem!important}.pt-3,.py-3{padding-top:1rem!important}.pr-3,.px-3{padding-right:1rem!important}.pb-3,.py-3{padding-bottom:1rem!important}.pl-3,.px-3{padding-left:1rem!important}.p-4{padding:1.5rem!important}.pt-4,.py-4{padding-top:1.5rem!important}.pr-4,.px-4{padding-right:1.5rem!important}.pb-4,.py-4{padding-bottom:1.5rem!important}.pl-4,.px-4{padding-left:1.5rem!important}.p-5{padding:3rem!important}.pt-5,.py-5{padding-top:3rem!important}.pr-5,.px-5{padding-right:3rem!important}.pb-5,.py-5{padding-bottom:3rem!important}.pl-5,.px-5{padding-left:3rem!important}.m-n1{margin:-.25rem!important}.mt-n1,.my-n1{margin-top:-.25rem!important}.mr-n1,.mx-n1{margin-right:-.25rem!important}.mb-n1,.my-n1{margin-bottom:-.25rem!important}.ml-n1,.mx-n1{margin-left:-.25rem!important}.m-n2{margin:-.5rem!important}.mt-n2,.my-n2{margin-top:-.5rem!important}.mr-n2,.mx-n2{margin-right:-.5rem!important}.mb-n2,.my-n2{margin-bottom:-.5rem!important}.ml-n2,.mx-n2{margin-left:-.5rem!important}.m-n3{margin:-1rem!important}.mt-n3,.my-n3{margin-top:-1rem!important}.mr-n3,.mx-n3{margin-right:-1rem!important}.mb-n3,.my-n3{margin-bottom:-1rem!important}.ml-n3,.mx-n3{margin-left:-1rem!important}.m-n4{margin:-1.5rem!important}.mt-n4,.my-n4{margin-top:-1.5rem!important}.mr-n4,.mx-n4{margin-right:-1.5rem!important}.mb-n4,.my-n4{margin-bottom:-1.5rem!important}.ml-n4,.mx-n4{margin-left:-1.5rem!important}.m-n5{margin:-3rem!important}.mt-n5,.my-n5{margin-top:-3rem!important}.mr-n5,.mx-n5{margin-right:-3rem!important}.mb-n5,.my-n5{margin-bottom:-3rem!important}.ml-n5,.mx-n5{margin-left:-3rem!important}.m-auto{margin:auto!important}.mt-auto,.my-auto{margin-top:auto!important}.mr-auto,.mx-auto{margin-right:auto!important}.mb-auto,.my-auto{margin-bottom:auto!important}.ml-auto,.mx-auto{margin-left:auto!important}@media (min-width:2px){.m-sm-0{margin:0!important}.mt-sm-0,.my-sm-0{margin-top:0!important}.mr-sm-0,.mx-sm-0{margin-right:0!important}.mb-sm-0,.my-sm-0{margin-bottom:0!important}.ml-sm-0,.mx-sm-0{margin-left:0!important}.m-sm-1{margin:.25rem!important}.mt-sm-1,.my-sm-1{margin-top:.25rem!important}.mr-sm-1,.mx-sm-1{margin-right:.25rem!important}.mb-sm-1,.my-sm-1{margin-bottom:.25rem!important}.ml-sm-1,.mx-sm-1{margin-left:.25rem!important}.m-sm-2{margin:.5rem!important}.mt-sm-2,.my-sm-2{margin-top:.5rem!important}.mr-sm-2,.mx-sm-2{margin-right:.5rem!important}.mb-sm-2,.my-sm-2{margin-bottom:.5rem!important}.ml-sm-2,.mx-sm-2{margin-left:.5rem!important}.m-sm-3{margin:1rem!important}.mt-sm-3,.my-sm-3{margin-top:1rem!important}.mr-sm-3,.mx-sm-3{margin-right:1rem!important}.mb-sm-3,.my-sm-3{margin-bottom:1rem!important}.ml-sm-3,.mx-sm-3{margin-left:1rem!important}.m-sm-4{margin:1.5rem!important}.mt-sm-4,.my-sm-4{margin-top:1.5rem!important}.mr-sm-4,.mx-sm-4{margin-right:1.5rem!important}.mb-sm-4,.my-sm-4{margin-bottom:1.5rem!important}.ml-sm-4,.mx-sm-4{margin-left:1.5rem!important}.m-sm-5{margin:3rem!important}.mt-sm-5,.my-sm-5{margin-top:3rem!important}.mr-sm-5,.mx-sm-5{margin-right:3rem!important}.mb-sm-5,.my-sm-5{margin-bottom:3rem!important}.ml-sm-5,.mx-sm-5{margin-left:3rem!important}.p-sm-0{padding:0!important}.pt-sm-0,.py-sm-0{padding-top:0!important}.pr-sm-0,.px-sm-0{padding-right:0!important}.pb-sm-0,.py-sm-0{padding-bottom:0!important}.pl-sm-0,.px-sm-0{padding-left:0!important}.p-sm-1{padding:.25rem!important}.pt-sm-1,.py-sm-1{padding-top:.25rem!important}.pr-sm-1,.px-sm-1{padding-right:.25rem!important}.pb-sm-1,.py-sm-1{padding-bottom:.25rem!important}.pl-sm-1,.px-sm-1{padding-left:.25rem!important}.p-sm-2{padding:.5rem!important}.pt-sm-2,.py-sm-2{padding-top:.5rem!important}.pr-sm-2,.px-sm-2{padding-right:.5rem!important}.pb-sm-2,.py-sm-2{padding-bottom:.5rem!important}.pl-sm-2,.px-sm-2{padding-left:.5rem!important}.p-sm-3{padding:1rem!important}.pt-sm-3,.py-sm-3{padding-top:1rem!important}.pr-sm-3,.px-sm-3{padding-right:1rem!important}.pb-sm-3,.py-sm-3{padding-bottom:1rem!important}.pl-sm-3,.px-sm-3{padding-left:1rem!important}.p-sm-4{padding:1.5rem!important}.pt-sm-4,.py-sm-4{padding-top:1.5rem!important}.pr-sm-4,.px-sm-4{padding-right:1.5rem!important}.pb-sm-4,.py-sm-4{padding-bottom:1.5rem!important}.pl-sm-4,.px-sm-4{padding-left:1.5rem!important}.p-sm-5{padding:3rem!important}.pt-sm-5,.py-sm-5{padding-top:3rem!important}.pr-sm-5,.px-sm-5{padding-right:3rem!important}.pb-sm-5,.py-sm-5{padding-bottom:3rem!important}.pl-sm-5,.px-sm-5{padding-left:3rem!important}.m-sm-n1{margin:-.25rem!important}.mt-sm-n1,.my-sm-n1{margin-top:-.25rem!important}.mr-sm-n1,.mx-sm-n1{margin-right:-.25rem!important}.mb-sm-n1,.my-sm-n1{margin-bottom:-.25rem!important}.ml-sm-n1,.mx-sm-n1{margin-left:-.25rem!important}.m-sm-n2{margin:-.5rem!important}.mt-sm-n2,.my-sm-n2{margin-top:-.5rem!important}.mr-sm-n2,.mx-sm-n2{margin-right:-.5rem!important}.mb-sm-n2,.my-sm-n2{margin-bottom:-.5rem!important}.ml-sm-n2,.mx-sm-n2{margin-left:-.5rem!important}.m-sm-n3{margin:-1rem!important}.mt-sm-n3,.my-sm-n3{margin-top:-1rem!important}.mr-sm-n3,.mx-sm-n3{margin-right:-1rem!important}.mb-sm-n3,.my-sm-n3{margin-bottom:-1rem!important}.ml-sm-n3,.mx-sm-n3{margin-left:-1rem!important}.m-sm-n4{margin:-1.5rem!important}.mt-sm-n4,.my-sm-n4{margin-top:-1.5rem!important}.mr-sm-n4,.mx-sm-n4{margin-right:-1.5rem!important}.mb-sm-n4,.my-sm-n4{margin-bottom:-1.5rem!important}.ml-sm-n4,.mx-sm-n4{margin-left:-1.5rem!important}.m-sm-n5{margin:-3rem!important}.mt-sm-n5,.my-sm-n5{margin-top:-3rem!important}.mr-sm-n5,.mx-sm-n5{margin-right:-3rem!important}.mb-sm-n5,.my-sm-n5{margin-bottom:-3rem!important}.ml-sm-n5,.mx-sm-n5{margin-left:-3rem!important}.m-sm-auto{margin:auto!important}.mt-sm-auto,.my-sm-auto{margin-top:auto!important}.mr-sm-auto,.mx-sm-auto{margin-right:auto!important}.mb-sm-auto,.my-sm-auto{margin-bottom:auto!important}.ml-sm-auto,.mx-sm-auto{margin-left:auto!important}}@media (min-width:8px){.m-md-0{margin:0!important}.mt-md-0,.my-md-0{margin-top:0!important}.mr-md-0,.mx-md-0{margin-right:0!important}.mb-md-0,.my-md-0{margin-bottom:0!important}.ml-md-0,.mx-md-0{margin-left:0!important}.m-md-1{margin:.25rem!important}.mt-md-1,.my-md-1{margin-top:.25rem!important}.mr-md-1,.mx-md-1{margin-right:.25rem!important}.mb-md-1,.my-md-1{margin-bottom:.25rem!important}.ml-md-1,.mx-md-1{margin-left:.25rem!important}.m-md-2{margin:.5rem!important}.mt-md-2,.my-md-2{margin-top:.5rem!important}.mr-md-2,.mx-md-2{margin-right:.5rem!important}.mb-md-2,.my-md-2{margin-bottom:.5rem!important}.ml-md-2,.mx-md-2{margin-left:.5rem!important}.m-md-3{margin:1rem!important}.mt-md-3,.my-md-3{margin-top:1rem!important}.mr-md-3,.mx-md-3{margin-right:1rem!important}.mb-md-3,.my-md-3{margin-bottom:1rem!important}.ml-md-3,.mx-md-3{margin-left:1rem!important}.m-md-4{margin:1.5rem!important}.mt-md-4,.my-md-4{margin-top:1.5rem!important}.mr-md-4,.mx-md-4{margin-right:1.5rem!important}.mb-md-4,.my-md-4{margin-bottom:1.5rem!important}.ml-md-4,.mx-md-4{margin-left:1.5rem!important}.m-md-5{margin:3rem!important}.mt-md-5,.my-md-5{margin-top:3rem!important}.mr-md-5,.mx-md-5{margin-right:3rem!important}.mb-md-5,.my-md-5{margin-bottom:3rem!important}.ml-md-5,.mx-md-5{margin-left:3rem!important}.p-md-0{padding:0!important}.pt-md-0,.py-md-0{padding-top:0!important}.pr-md-0,.px-md-0{padding-right:0!important}.pb-md-0,.py-md-0{padding-bottom:0!important}.pl-md-0,.px-md-0{padding-left:0!important}.p-md-1{padding:.25rem!important}.pt-md-1,.py-md-1{padding-top:.25rem!important}.pr-md-1,.px-md-1{padding-right:.25rem!important}.pb-md-1,.py-md-1{padding-bottom:.25rem!important}.pl-md-1,.px-md-1{padding-left:.25rem!important}.p-md-2{padding:.5rem!important}.pt-md-2,.py-md-2{padding-top:.5rem!important}.pr-md-2,.px-md-2{padding-right:.5rem!important}.pb-md-2,.py-md-2{padding-bottom:.5rem!important}.pl-md-2,.px-md-2{padding-left:.5rem!important}.p-md-3{padding:1rem!important}.pt-md-3,.py-md-3{padding-top:1rem!important}.pr-md-3,.px-md-3{padding-right:1rem!important}.pb-md-3,.py-md-3{padding-bottom:1rem!important}.pl-md-3,.px-md-3{padding-left:1rem!important}.p-md-4{padding:1.5rem!important}.pt-md-4,.py-md-4{padding-top:1.5rem!important}.pr-md-4,.px-md-4{padding-right:1.5rem!important}.pb-md-4,.py-md-4{padding-bottom:1.5rem!important}.pl-md-4,.px-md-4{padding-left:1.5rem!important}.p-md-5{padding:3rem!important}.pt-md-5,.py-md-5{padding-top:3rem!important}.pr-md-5,.px-md-5{padding-right:3rem!important}.pb-md-5,.py-md-5{padding-bottom:3rem!important}.pl-md-5,.px-md-5{padding-left:3rem!important}.m-md-n1{margin:-.25rem!important}.mt-md-n1,.my-md-n1{margin-top:-.25rem!important}.mr-md-n1,.mx-md-n1{margin-right:-.25rem!important}.mb-md-n1,.my-md-n1{margin-bottom:-.25rem!important}.ml-md-n1,.mx-md-n1{margin-left:-.25rem!important}.m-md-n2{margin:-.5rem!important}.mt-md-n2,.my-md-n2{margin-top:-.5rem!important}.mr-md-n2,.mx-md-n2{margin-right:-.5rem!important}.mb-md-n2,.my-md-n2{margin-bottom:-.5rem!important}.ml-md-n2,.mx-md-n2{margin-left:-.5rem!important}.m-md-n3{margin:-1rem!important}.mt-md-n3,.my-md-n3{margin-top:-1rem!important}.mr-md-n3,.mx-md-n3{margin-right:-1rem!important}.mb-md-n3,.my-md-n3{margin-bottom:-1rem!important}.ml-md-n3,.mx-md-n3{margin-left:-1rem!important}.m-md-n4{margin:-1.5rem!important}.mt-md-n4,.my-md-n4{margin-top:-1.5rem!important}.mr-md-n4,.mx-md-n4{margin-right:-1.5rem!important}.mb-md-n4,.my-md-n4{margin-bottom:-1.5rem!important}.ml-md-n4,.mx-md-n4{margin-left:-1.5rem!important}.m-md-n5{margin:-3rem!important}.mt-md-n5,.my-md-n5{margin-top:-3rem!important}.mr-md-n5,.mx-md-n5{margin-right:-3rem!important}.mb-md-n5,.my-md-n5{margin-bottom:-3rem!important}.ml-md-n5,.mx-md-n5{margin-left:-3rem!important}.m-md-auto{margin:auto!important}.mt-md-auto,.my-md-auto{margin-top:auto!important}.mr-md-auto,.mx-md-auto{margin-right:auto!important}.mb-md-auto,.my-md-auto{margin-bottom:auto!important}.ml-md-auto,.mx-md-auto{margin-left:auto!important}}@media (min-width:9px){.m-lg-0{margin:0!important}.mt-lg-0,.my-lg-0{margin-top:0!important}.mr-lg-0,.mx-lg-0{margin-right:0!important}.mb-lg-0,.my-lg-0{margin-bottom:0!important}.ml-lg-0,.mx-lg-0{margin-left:0!important}.m-lg-1{margin:.25rem!important}.mt-lg-1,.my-lg-1{margin-top:.25rem!important}.mr-lg-1,.mx-lg-1{margin-right:.25rem!important}.mb-lg-1,.my-lg-1{margin-bottom:.25rem!important}.ml-lg-1,.mx-lg-1{margin-left:.25rem!important}.m-lg-2{margin:.5rem!important}.mt-lg-2,.my-lg-2{margin-top:.5rem!important}.mr-lg-2,.mx-lg-2{margin-right:.5rem!important}.mb-lg-2,.my-lg-2{margin-bottom:.5rem!important}.ml-lg-2,.mx-lg-2{margin-left:.5rem!important}.m-lg-3{margin:1rem!important}.mt-lg-3,.my-lg-3{margin-top:1rem!important}.mr-lg-3,.mx-lg-3{margin-right:1rem!important}.mb-lg-3,.my-lg-3{margin-bottom:1rem!important}.ml-lg-3,.mx-lg-3{margin-left:1rem!important}.m-lg-4{margin:1.5rem!important}.mt-lg-4,.my-lg-4{margin-top:1.5rem!important}.mr-lg-4,.mx-lg-4{margin-right:1.5rem!important}.mb-lg-4,.my-lg-4{margin-bottom:1.5rem!important}.ml-lg-4,.mx-lg-4{margin-left:1.5rem!important}.m-lg-5{margin:3rem!important}.mt-lg-5,.my-lg-5{margin-top:3rem!important}.mr-lg-5,.mx-lg-5{margin-right:3rem!important}.mb-lg-5,.my-lg-5{margin-bottom:3rem!important}.ml-lg-5,.mx-lg-5{margin-left:3rem!important}.p-lg-0{padding:0!important}.pt-lg-0,.py-lg-0{padding-top:0!important}.pr-lg-0,.px-lg-0{padding-right:0!important}.pb-lg-0,.py-lg-0{padding-bottom:0!important}.pl-lg-0,.px-lg-0{padding-left:0!important}.p-lg-1{padding:.25rem!important}.pt-lg-1,.py-lg-1{padding-top:.25rem!important}.pr-lg-1,.px-lg-1{padding-right:.25rem!important}.pb-lg-1,.py-lg-1{padding-bottom:.25rem!important}.pl-lg-1,.px-lg-1{padding-left:.25rem!important}.p-lg-2{padding:.5rem!important}.pt-lg-2,.py-lg-2{padding-top:.5rem!important}.pr-lg-2,.px-lg-2{padding-right:.5rem!important}.pb-lg-2,.py-lg-2{padding-bottom:.5rem!important}.pl-lg-2,.px-lg-2{padding-left:.5rem!important}.p-lg-3{padding:1rem!important}.pt-lg-3,.py-lg-3{padding-top:1rem!important}.pr-lg-3,.px-lg-3{padding-right:1rem!important}.pb-lg-3,.py-lg-3{padding-bottom:1rem!important}.pl-lg-3,.px-lg-3{padding-left:1rem!important}.p-lg-4{padding:1.5rem!important}.pt-lg-4,.py-lg-4{padding-top:1.5rem!important}.pr-lg-4,.px-lg-4{padding-right:1.5rem!important}.pb-lg-4,.py-lg-4{padding-bottom:1.5rem!important}.pl-lg-4,.px-lg-4{padding-left:1.5rem!important}.p-lg-5{padding:3rem!important}.pt-lg-5,.py-lg-5{padding-top:3rem!important}.pr-lg-5,.px-lg-5{padding-right:3rem!important}.pb-lg-5,.py-lg-5{padding-bottom:3rem!important}.pl-lg-5,.px-lg-5{padding-left:3rem!important}.m-lg-n1{margin:-.25rem!important}.mt-lg-n1,.my-lg-n1{margin-top:-.25rem!important}.mr-lg-n1,.mx-lg-n1{margin-right:-.25rem!important}.mb-lg-n1,.my-lg-n1{margin-bottom:-.25rem!important}.ml-lg-n1,.mx-lg-n1{margin-left:-.25rem!important}.m-lg-n2{margin:-.5rem!important}.mt-lg-n2,.my-lg-n2{margin-top:-.5rem!important}.mr-lg-n2,.mx-lg-n2{margin-right:-.5rem!important}.mb-lg-n2,.my-lg-n2{margin-bottom:-.5rem!important}.ml-lg-n2,.mx-lg-n2{margin-left:-.5rem!important}.m-lg-n3{margin:-1rem!important}.mt-lg-n3,.my-lg-n3{margin-top:-1rem!important}.mr-lg-n3,.mx-lg-n3{margin-right:-1rem!important}.mb-lg-n3,.my-lg-n3{margin-bottom:-1rem!important}.ml-lg-n3,.mx-lg-n3{margin-left:-1rem!important}.m-lg-n4{margin:-1.5rem!important}.mt-lg-n4,.my-lg-n4{margin-top:-1.5rem!important}.mr-lg-n4,.mx-lg-n4{margin-right:-1.5rem!important}.mb-lg-n4,.my-lg-n4{margin-bottom:-1.5rem!important}.ml-lg-n4,.mx-lg-n4{margin-left:-1.5rem!important}.m-lg-n5{margin:-3rem!important}.mt-lg-n5,.my-lg-n5{margin-top:-3rem!important}.mr-lg-n5,.mx-lg-n5{margin-right:-3rem!important}.mb-lg-n5,.my-lg-n5{margin-bottom:-3rem!important}.ml-lg-n5,.mx-lg-n5{margin-left:-3rem!important}.m-lg-auto{margin:auto!important}.mt-lg-auto,.my-lg-auto{margin-top:auto!important}.mr-lg-auto,.mx-lg-auto{margin-right:auto!important}.mb-lg-auto,.my-lg-auto{margin-bottom:auto!important}.ml-lg-auto,.mx-lg-auto{margin-left:auto!important}}@media (min-width:10px){.m-xl-0{margin:0!important}.mt-xl-0,.my-xl-0{margin-top:0!important}.mr-xl-0,.mx-xl-0{margin-right:0!important}.mb-xl-0,.my-xl-0{margin-bottom:0!important}.ml-xl-0,.mx-xl-0{margin-left:0!important}.m-xl-1{margin:.25rem!important}.mt-xl-1,.my-xl-1{margin-top:.25rem!important}.mr-xl-1,.mx-xl-1{margin-right:.25rem!important}.mb-xl-1,.my-xl-1{margin-bottom:.25rem!important}.ml-xl-1,.mx-xl-1{margin-left:.25rem!important}.m-xl-2{margin:.5rem!important}.mt-xl-2,.my-xl-2{margin-top:.5rem!important}.mr-xl-2,.mx-xl-2{margin-right:.5rem!important}.mb-xl-2,.my-xl-2{margin-bottom:.5rem!important}.ml-xl-2,.mx-xl-2{margin-left:.5rem!important}.m-xl-3{margin:1rem!important}.mt-xl-3,.my-xl-3{margin-top:1rem!important}.mr-xl-3,.mx-xl-3{margin-right:1rem!important}.mb-xl-3,.my-xl-3{margin-bottom:1rem!important}.ml-xl-3,.mx-xl-3{margin-left:1rem!important}.m-xl-4{margin:1.5rem!important}.mt-xl-4,.my-xl-4{margin-top:1.5rem!important}.mr-xl-4,.mx-xl-4{margin-right:1.5rem!important}.mb-xl-4,.my-xl-4{margin-bottom:1.5rem!important}.ml-xl-4,.mx-xl-4{margin-left:1.5rem!important}.m-xl-5{margin:3rem!important}.mt-xl-5,.my-xl-5{margin-top:3rem!important}.mr-xl-5,.mx-xl-5{margin-right:3rem!important}.mb-xl-5,.my-xl-5{margin-bottom:3rem!important}.ml-xl-5,.mx-xl-5{margin-left:3rem!important}.p-xl-0{padding:0!important}.pt-xl-0,.py-xl-0{padding-top:0!important}.pr-xl-0,.px-xl-0{padding-right:0!important}.pb-xl-0,.py-xl-0{padding-bottom:0!important}.pl-xl-0,.px-xl-0{padding-left:0!important}.p-xl-1{padding:.25rem!important}.pt-xl-1,.py-xl-1{padding-top:.25rem!important}.pr-xl-1,.px-xl-1{padding-right:.25rem!important}.pb-xl-1,.py-xl-1{padding-bottom:.25rem!important}.pl-xl-1,.px-xl-1{padding-left:.25rem!important}.p-xl-2{padding:.5rem!important}.pt-xl-2,.py-xl-2{padding-top:.5rem!important}.pr-xl-2,.px-xl-2{padding-right:.5rem!important}.pb-xl-2,.py-xl-2{padding-bottom:.5rem!important}.pl-xl-2,.px-xl-2{padding-left:.5rem!important}.p-xl-3{padding:1rem!important}.pt-xl-3,.py-xl-3{padding-top:1rem!important}.pr-xl-3,.px-xl-3{padding-right:1rem!important}.pb-xl-3,.py-xl-3{padding-bottom:1rem!important}.pl-xl-3,.px-xl-3{padding-left:1rem!important}.p-xl-4{padding:1.5rem!important}.pt-xl-4,.py-xl-4{padding-top:1.5rem!important}.pr-xl-4,.px-xl-4{padding-right:1.5rem!important}.pb-xl-4,.py-xl-4{padding-bottom:1.5rem!important}.pl-xl-4,.px-xl-4{padding-left:1.5rem!important}.p-xl-5{padding:3rem!important}.pt-xl-5,.py-xl-5{padding-top:3rem!important}.pr-xl-5,.px-xl-5{padding-right:3rem!important}.pb-xl-5,.py-xl-5{padding-bottom:3rem!important}.pl-xl-5,.px-xl-5{padding-left:3rem!important}.m-xl-n1{margin:-.25rem!important}.mt-xl-n1,.my-xl-n1{margin-top:-.25rem!important}.mr-xl-n1,.mx-xl-n1{margin-right:-.25rem!important}.mb-xl-n1,.my-xl-n1{margin-bottom:-.25rem!important}.ml-xl-n1,.mx-xl-n1{margin-left:-.25rem!important}.m-xl-n2{margin:-.5rem!important}.mt-xl-n2,.my-xl-n2{margin-top:-.5rem!important}.mr-xl-n2,.mx-xl-n2{margin-right:-.5rem!important}.mb-xl-n2,.my-xl-n2{margin-bottom:-.5rem!important}.ml-xl-n2,.mx-xl-n2{margin-left:-.5rem!important}.m-xl-n3{margin:-1rem!important}.mt-xl-n3,.my-xl-n3{margin-top:-1rem!important}.mr-xl-n3,.mx-xl-n3{margin-right:-1rem!important}.mb-xl-n3,.my-xl-n3{margin-bottom:-1rem!important}.ml-xl-n3,.mx-xl-n3{margin-left:-1rem!important}.m-xl-n4{margin:-1.5rem!important}.mt-xl-n4,.my-xl-n4{margin-top:-1.5rem!important}.mr-xl-n4,.mx-xl-n4{margin-right:-1.5rem!important}.mb-xl-n4,.my-xl-n4{margin-bottom:-1.5rem!important}.ml-xl-n4,.mx-xl-n4{margin-left:-1.5rem!important}.m-xl-n5{margin:-3rem!important}.mt-xl-n5,.my-xl-n5{margin-top:-3rem!important}.mr-xl-n5,.mx-xl-n5{margin-right:-3rem!important}.mb-xl-n5,.my-xl-n5{margin-bottom:-3rem!important}.ml-xl-n5,.mx-xl-n5{margin-left:-3rem!important}.m-xl-auto{margin:auto!important}.mt-xl-auto,.my-xl-auto{margin-top:auto!important}.mr-xl-auto,.mx-xl-auto{margin-right:auto!important}.mb-xl-auto,.my-xl-auto{margin-bottom:auto!important}.ml-xl-auto,.mx-xl-auto{margin-left:auto!important}}.stretched-link:after{background-color:transparent;bottom:0;content:"";left:0;pointer-events:auto;position:absolute;right:0;top:0;z-index:1}.text-monospace{font-family:SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace!important}.text-justify{text-align:justify!important}.text-wrap{white-space:normal!important}.text-nowrap{white-space:nowrap!important}.text-truncate{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.text-left{text-align:left!important}.text-right{text-align:right!important}.text-center{text-align:center!important}@media (min-width:2px){.text-sm-left{text-align:left!important}.text-sm-right{text-align:right!important}.text-sm-center{text-align:center!important}}@media (min-width:8px){.text-md-left{text-align:left!important}.text-md-right{text-align:right!important}.text-md-center{text-align:center!important}}@media (min-width:9px){.text-lg-left{text-align:left!important}.text-lg-right{text-align:right!important}.text-lg-center{text-align:center!important}}@media (min-width:10px){.text-xl-left{text-align:left!important}.text-xl-right{text-align:right!important}.text-xl-center{text-align:center!important}}.text-lowercase{text-transform:lowercase!important}.text-uppercase{text-transform:uppercase!important}.text-capitalize{text-transform:capitalize!important}.font-weight-light{font-weight:300!important}.font-weight-lighter{font-weight:lighter!important}.font-weight-normal{font-weight:400!important}.font-weight-bold{font-weight:700!important}.font-weight-bolder{font-weight:bolder!important}.font-italic{font-style:italic!important}.text-white{color:#fff!important}.text-primary{color:#7746ec!important}a.text-primary:focus,a.text-primary:hover{color:#4d15d0!important}.text-secondary{color:#dae1e7!important}a.text-secondary:focus,a.text-secondary:hover{color:#acbbc9!important}.text-success{color:#51d88a!important}a.text-success:focus,a.text-success:hover{color:#28b463!important}.text-info{color:#bcdefa!important}a.text-info:focus,a.text-info:hover{color:#75bbf5!important}.text-warning{color:#ffa260!important}a.text-warning:focus,a.text-warning:hover{color:#ff7514!important}.text-danger{color:#ef5753!important}a.text-danger:focus,a.text-danger:hover{color:#e11a15!important}.text-light{color:#f8f9fa!important}a.text-light:focus,a.text-light:hover{color:#cbd3da!important}.text-dark{color:#343a40!important}a.text-dark:focus,a.text-dark:hover{color:#121416!important}.text-body{color:#212529!important}.text-muted{color:#6c757d!important}.text-black-50{color:rgba(0,0,0,.5)!important}.text-white-50{color:hsla(0,0%,100%,.5)!important}.text-hide{background-color:transparent;border:0;color:transparent;font:0/0 a;text-shadow:none}.text-decoration-none{text-decoration:none!important}.text-break{word-wrap:break-word!important;word-break:break-word!important}.text-reset{color:inherit!important}.visible{visibility:visible!important}.invisible{visibility:hidden!important}@media print{*,:after,:before{box-shadow:none!important;text-shadow:none!important}a:not(.btn){text-decoration:underline}abbr[title]:after{content:" (" attr(title) ")"}pre{white-space:pre-wrap!important}blockquote,pre{border:1px solid #adb5bd}blockquote,img,pre,tr{page-break-inside:avoid}h2,h3,p{orphans:3;widows:3}h2,h3{page-break-after:avoid}@page{size:a3}.container,body{min-width:9px!important}.navbar{display:none}.badge{border:1px solid #000}.table{border-collapse:collapse!important}.table td,.table th{background-color:#fff!important}.table-bordered td,.table-bordered th{border:1px solid #dee2e6!important}.table-dark{color:inherit}.table-dark tbody+tbody,.table-dark td,.table-dark th,.table-dark thead th{border-color:#efefef}.table .thead-dark th{border-color:#efefef;color:inherit}}body{padding-bottom:20px}.container{width:1140px}html{min-width:1140px}[v-cloak]{display:none}svg.icon{height:1rem;width:1rem}.header{border-bottom:1px solid #d5dfe9}.header svg.logo{height:2rem;width:2rem}.sidebar .nav-item a{color:#2a5164;padding:.5rem 0}.sidebar .nav-item a svg{fill:#c3cbd3;height:1rem;margin-right:15px;width:1rem}.sidebar .nav-item a.active{color:#7746ec}.sidebar .nav-item a.active svg{fill:#7746ec}.card{border:none;box-shadow:0 2px 3px #cdd8df}.card .bottom-radius{border-bottom-left-radius:.25rem;border-bottom-right-radius:.25rem}.card .card-header{background-color:#fff;border-bottom:none;padding-bottom:.7rem;padding-top:.7rem}.card .card-header .btn-group .btn{padding:.2rem .5rem}.card .card-header h5{margin:0}.card .table td,.card .table th{padding:.75rem 1.25rem}.card .table.table-sm td,.card .table.table-sm th{padding:1rem 1.25rem}.card .table th{background-color:#f3f4f6;border-bottom:0;font-weight:400;padding:.5rem 1.25rem}.card .table:not(.table-borderless) td{border-top:1px solid #efefef}.card .table.penultimate-column-right td:nth-last-child(2),.card .table.penultimate-column-right th:nth-last-child(2){text-align:right}.card .table td.table-fit,.card .table th.table-fit{white-space:nowrap;width:1%}.fill-text-color{fill:#212529}.fill-danger{fill:#ef5753}.fill-warning{fill:#ffa260}.fill-info{fill:#bcdefa}.fill-success{fill:#51d88a}.fill-primary{fill:#7746ec}button:hover .fill-primary{fill:#fff}.btn-outline-primary.active .fill-primary{fill:#ebebeb}.btn-outline-primary:not(:disabled):not(.disabled).active:focus{box-shadow:none!important}.control-action svg{fill:#ccd2df;height:1.2rem;width:1.2rem}.control-action svg:hover{fill:#7746ec}.info-icon{fill:#ccd2df}.paginator .btn{color:#9ea7ac;text-decoration:none}.paginator .btn:hover{color:#7746ec}@keyframes spin{0%{transform:rotate(0deg)}to{transform:rotate(1turn)}}.spin{animation:spin 2s linear infinite}.card .nav-pills .nav-link.active{background:none;border-bottom:2px solid #7746ec;color:#7746ec}.card .nav-pills .nav-link{border-radius:0;color:#212529;font-size:.9rem;padding:.75rem 1.25rem}.list-enter-active:not(.dontanimate){transition:background 1s linear}.list-enter:not(.dontanimate),.list-leave-to:not(.dontanimate){background:#fffee9}.card table td{vertical-align:middle!important}.card-bg-secondary{background:#fafafa}.code-bg{background:#120f12}.disabled-watcher{background:#ef5753;color:#fff;padding:.75rem}.badge-sm{font-size:.75rem} diff --git a/public/vendor/horizon/app.js b/public/vendor/horizon/app.js new file mode 100644 index 00000000..8a938166 --- /dev/null +++ b/public/vendor/horizon/app.js @@ -0,0 +1,2 @@ +/*! For license information please see app.js.LICENSE.txt */ +(()=>{var t,e={9669:(t,e,o)=>{t.exports=o(1609)},5448:(t,e,o)=>{"use strict";var n=o(4867),p=o(6026),b=o(4372),M=o(5327),z=o(4097),r=o(4109),c=o(7985),i=o(5061);t.exports=function(t){return new Promise((function(e,o){var a=t.data,O=t.headers,s=t.responseType;n.isFormData(a)&&delete O["Content-Type"];var l=new XMLHttpRequest;if(t.auth){var d=t.auth.username||"",u=t.auth.password?unescape(encodeURIComponent(t.auth.password)):"";O.Authorization="Basic "+btoa(d+":"+u)}var A=z(t.baseURL,t.url);function f(){if(l){var n="getAllResponseHeaders"in l?r(l.getAllResponseHeaders()):null,b={data:s&&"text"!==s&&"json"!==s?l.response:l.responseText,status:l.status,statusText:l.statusText,headers:n,config:t,request:l};p(e,o,b),l=null}}if(l.open(t.method.toUpperCase(),M(A,t.params,t.paramsSerializer),!0),l.timeout=t.timeout,"onloadend"in l?l.onloadend=f:l.onreadystatechange=function(){l&&4===l.readyState&&(0!==l.status||l.responseURL&&0===l.responseURL.indexOf("file:"))&&setTimeout(f)},l.onabort=function(){l&&(o(i("Request aborted",t,"ECONNABORTED",l)),l=null)},l.onerror=function(){o(i("Network Error",t,null,l)),l=null},l.ontimeout=function(){var e="timeout of "+t.timeout+"ms exceeded";t.timeoutErrorMessage&&(e=t.timeoutErrorMessage),o(i(e,t,t.transitional&&t.transitional.clarifyTimeoutError?"ETIMEDOUT":"ECONNABORTED",l)),l=null},n.isStandardBrowserEnv()){var q=(t.withCredentials||c(A))&&t.xsrfCookieName?b.read(t.xsrfCookieName):void 0;q&&(O[t.xsrfHeaderName]=q)}"setRequestHeader"in l&&n.forEach(O,(function(t,e){void 0===a&&"content-type"===e.toLowerCase()?delete O[e]:l.setRequestHeader(e,t)})),n.isUndefined(t.withCredentials)||(l.withCredentials=!!t.withCredentials),s&&"json"!==s&&(l.responseType=t.responseType),"function"==typeof t.onDownloadProgress&&l.addEventListener("progress",t.onDownloadProgress),"function"==typeof t.onUploadProgress&&l.upload&&l.upload.addEventListener("progress",t.onUploadProgress),t.cancelToken&&t.cancelToken.promise.then((function(t){l&&(l.abort(),o(t),l=null)})),a||(a=null),l.send(a)}))}},1609:(t,e,o)=>{"use strict";var n=o(4867),p=o(1849),b=o(321),M=o(7185);function z(t){var e=new b(t),o=p(b.prototype.request,e);return n.extend(o,b.prototype,e),n.extend(o,e),o}var r=z(o(5655));r.Axios=b,r.create=function(t){return z(M(r.defaults,t))},r.Cancel=o(5263),r.CancelToken=o(4972),r.isCancel=o(6502),r.all=function(t){return Promise.all(t)},r.spread=o(8713),r.isAxiosError=o(6268),t.exports=r,t.exports.default=r},5263:t=>{"use strict";function e(t){this.message=t}e.prototype.toString=function(){return"Cancel"+(this.message?": "+this.message:"")},e.prototype.__CANCEL__=!0,t.exports=e},4972:(t,e,o)=>{"use strict";var n=o(5263);function p(t){if("function"!=typeof t)throw new TypeError("executor must be a function.");var e;this.promise=new Promise((function(t){e=t}));var o=this;t((function(t){o.reason||(o.reason=new n(t),e(o.reason))}))}p.prototype.throwIfRequested=function(){if(this.reason)throw this.reason},p.source=function(){var t;return{token:new p((function(e){t=e})),cancel:t}},t.exports=p},6502:t=>{"use strict";t.exports=function(t){return!(!t||!t.__CANCEL__)}},321:(t,e,o)=>{"use strict";var n=o(4867),p=o(5327),b=o(782),M=o(3572),z=o(7185),r=o(4875),c=r.validators;function i(t){this.defaults=t,this.interceptors={request:new b,response:new b}}i.prototype.request=function(t){"string"==typeof t?(t=arguments[1]||{}).url=arguments[0]:t=t||{},(t=z(this.defaults,t)).method?t.method=t.method.toLowerCase():this.defaults.method?t.method=this.defaults.method.toLowerCase():t.method="get";var e=t.transitional;void 0!==e&&r.assertOptions(e,{silentJSONParsing:c.transitional(c.boolean,"1.0.0"),forcedJSONParsing:c.transitional(c.boolean,"1.0.0"),clarifyTimeoutError:c.transitional(c.boolean,"1.0.0")},!1);var o=[],n=!0;this.interceptors.request.forEach((function(e){"function"==typeof e.runWhen&&!1===e.runWhen(t)||(n=n&&e.synchronous,o.unshift(e.fulfilled,e.rejected))}));var p,b=[];if(this.interceptors.response.forEach((function(t){b.push(t.fulfilled,t.rejected)})),!n){var i=[M,void 0];for(Array.prototype.unshift.apply(i,o),i=i.concat(b),p=Promise.resolve(t);i.length;)p=p.then(i.shift(),i.shift());return p}for(var a=t;o.length;){var O=o.shift(),s=o.shift();try{a=O(a)}catch(t){s(t);break}}try{p=M(a)}catch(t){return Promise.reject(t)}for(;b.length;)p=p.then(b.shift(),b.shift());return p},i.prototype.getUri=function(t){return t=z(this.defaults,t),p(t.url,t.params,t.paramsSerializer).replace(/^\?/,"")},n.forEach(["delete","get","head","options"],(function(t){i.prototype[t]=function(e,o){return this.request(z(o||{},{method:t,url:e,data:(o||{}).data}))}})),n.forEach(["post","put","patch"],(function(t){i.prototype[t]=function(e,o,n){return this.request(z(n||{},{method:t,url:e,data:o}))}})),t.exports=i},782:(t,e,o)=>{"use strict";var n=o(4867);function p(){this.handlers=[]}p.prototype.use=function(t,e,o){return this.handlers.push({fulfilled:t,rejected:e,synchronous:!!o&&o.synchronous,runWhen:o?o.runWhen:null}),this.handlers.length-1},p.prototype.eject=function(t){this.handlers[t]&&(this.handlers[t]=null)},p.prototype.forEach=function(t){n.forEach(this.handlers,(function(e){null!==e&&t(e)}))},t.exports=p},4097:(t,e,o)=>{"use strict";var n=o(1793),p=o(7303);t.exports=function(t,e){return t&&!n(e)?p(t,e):e}},5061:(t,e,o)=>{"use strict";var n=o(481);t.exports=function(t,e,o,p,b){var M=new Error(t);return n(M,e,o,p,b)}},3572:(t,e,o)=>{"use strict";var n=o(4867),p=o(8527),b=o(6502),M=o(5655);function z(t){t.cancelToken&&t.cancelToken.throwIfRequested()}t.exports=function(t){return z(t),t.headers=t.headers||{},t.data=p.call(t,t.data,t.headers,t.transformRequest),t.headers=n.merge(t.headers.common||{},t.headers[t.method]||{},t.headers),n.forEach(["delete","get","head","post","put","patch","common"],(function(e){delete t.headers[e]})),(t.adapter||M.adapter)(t).then((function(e){return z(t),e.data=p.call(t,e.data,e.headers,t.transformResponse),e}),(function(e){return b(e)||(z(t),e&&e.response&&(e.response.data=p.call(t,e.response.data,e.response.headers,t.transformResponse))),Promise.reject(e)}))}},481:t=>{"use strict";t.exports=function(t,e,o,n,p){return t.config=e,o&&(t.code=o),t.request=n,t.response=p,t.isAxiosError=!0,t.toJSON=function(){return{message:this.message,name:this.name,description:this.description,number:this.number,fileName:this.fileName,lineNumber:this.lineNumber,columnNumber:this.columnNumber,stack:this.stack,config:this.config,code:this.code}},t}},7185:(t,e,o)=>{"use strict";var n=o(4867);t.exports=function(t,e){e=e||{};var o={},p=["url","method","data"],b=["headers","auth","proxy","params"],M=["baseURL","transformRequest","transformResponse","paramsSerializer","timeout","timeoutMessage","withCredentials","adapter","responseType","xsrfCookieName","xsrfHeaderName","onUploadProgress","onDownloadProgress","decompress","maxContentLength","maxBodyLength","maxRedirects","transport","httpAgent","httpsAgent","cancelToken","socketPath","responseEncoding"],z=["validateStatus"];function r(t,e){return n.isPlainObject(t)&&n.isPlainObject(e)?n.merge(t,e):n.isPlainObject(e)?n.merge({},e):n.isArray(e)?e.slice():e}function c(p){n.isUndefined(e[p])?n.isUndefined(t[p])||(o[p]=r(void 0,t[p])):o[p]=r(t[p],e[p])}n.forEach(p,(function(t){n.isUndefined(e[t])||(o[t]=r(void 0,e[t]))})),n.forEach(b,c),n.forEach(M,(function(p){n.isUndefined(e[p])?n.isUndefined(t[p])||(o[p]=r(void 0,t[p])):o[p]=r(void 0,e[p])})),n.forEach(z,(function(n){n in e?o[n]=r(t[n],e[n]):n in t&&(o[n]=r(void 0,t[n]))}));var i=p.concat(b).concat(M).concat(z),a=Object.keys(t).concat(Object.keys(e)).filter((function(t){return-1===i.indexOf(t)}));return n.forEach(a,c),o}},6026:(t,e,o)=>{"use strict";var n=o(5061);t.exports=function(t,e,o){var p=o.config.validateStatus;o.status&&p&&!p(o.status)?e(n("Request failed with status code "+o.status,o.config,null,o.request,o)):t(o)}},8527:(t,e,o)=>{"use strict";var n=o(4867),p=o(5655);t.exports=function(t,e,o){var b=this||p;return n.forEach(o,(function(o){t=o.call(b,t,e)})),t}},5655:(t,e,o)=>{"use strict";var n=o(4155),p=o(4867),b=o(6016),M=o(481),z={"Content-Type":"application/x-www-form-urlencoded"};function r(t,e){!p.isUndefined(t)&&p.isUndefined(t["Content-Type"])&&(t["Content-Type"]=e)}var c,i={transitional:{silentJSONParsing:!0,forcedJSONParsing:!0,clarifyTimeoutError:!1},adapter:(("undefined"!=typeof XMLHttpRequest||void 0!==n&&"[object process]"===Object.prototype.toString.call(n))&&(c=o(5448)),c),transformRequest:[function(t,e){return b(e,"Accept"),b(e,"Content-Type"),p.isFormData(t)||p.isArrayBuffer(t)||p.isBuffer(t)||p.isStream(t)||p.isFile(t)||p.isBlob(t)?t:p.isArrayBufferView(t)?t.buffer:p.isURLSearchParams(t)?(r(e,"application/x-www-form-urlencoded;charset=utf-8"),t.toString()):p.isObject(t)||e&&"application/json"===e["Content-Type"]?(r(e,"application/json"),function(t,e,o){if(p.isString(t))try{return(e||JSON.parse)(t),p.trim(t)}catch(t){if("SyntaxError"!==t.name)throw t}return(o||JSON.stringify)(t)}(t)):t}],transformResponse:[function(t){var e=this.transitional,o=e&&e.silentJSONParsing,n=e&&e.forcedJSONParsing,b=!o&&"json"===this.responseType;if(b||n&&p.isString(t)&&t.length)try{return JSON.parse(t)}catch(t){if(b){if("SyntaxError"===t.name)throw M(t,this,"E_JSON_PARSE");throw t}}return t}],timeout:0,xsrfCookieName:"XSRF-TOKEN",xsrfHeaderName:"X-XSRF-TOKEN",maxContentLength:-1,maxBodyLength:-1,validateStatus:function(t){return t>=200&&t<300}};i.headers={common:{Accept:"application/json, text/plain, */*"}},p.forEach(["delete","get","head"],(function(t){i.headers[t]={}})),p.forEach(["post","put","patch"],(function(t){i.headers[t]=p.merge(z)})),t.exports=i},1849:t=>{"use strict";t.exports=function(t,e){return function(){for(var o=new Array(arguments.length),n=0;n{"use strict";var n=o(4867);function p(t){return encodeURIComponent(t).replace(/%3A/gi,":").replace(/%24/g,"$").replace(/%2C/gi,",").replace(/%20/g,"+").replace(/%5B/gi,"[").replace(/%5D/gi,"]")}t.exports=function(t,e,o){if(!e)return t;var b;if(o)b=o(e);else if(n.isURLSearchParams(e))b=e.toString();else{var M=[];n.forEach(e,(function(t,e){null!=t&&(n.isArray(t)?e+="[]":t=[t],n.forEach(t,(function(t){n.isDate(t)?t=t.toISOString():n.isObject(t)&&(t=JSON.stringify(t)),M.push(p(e)+"="+p(t))})))})),b=M.join("&")}if(b){var z=t.indexOf("#");-1!==z&&(t=t.slice(0,z)),t+=(-1===t.indexOf("?")?"?":"&")+b}return t}},7303:t=>{"use strict";t.exports=function(t,e){return e?t.replace(/\/+$/,"")+"/"+e.replace(/^\/+/,""):t}},4372:(t,e,o)=>{"use strict";var n=o(4867);t.exports=n.isStandardBrowserEnv()?{write:function(t,e,o,p,b,M){var z=[];z.push(t+"="+encodeURIComponent(e)),n.isNumber(o)&&z.push("expires="+new Date(o).toGMTString()),n.isString(p)&&z.push("path="+p),n.isString(b)&&z.push("domain="+b),!0===M&&z.push("secure"),document.cookie=z.join("; ")},read:function(t){var e=document.cookie.match(new RegExp("(^|;\\s*)("+t+")=([^;]*)"));return e?decodeURIComponent(e[3]):null},remove:function(t){this.write(t,"",Date.now()-864e5)}}:{write:function(){},read:function(){return null},remove:function(){}}},1793:t=>{"use strict";t.exports=function(t){return/^([a-z][a-z\d\+\-\.]*:)?\/\//i.test(t)}},6268:t=>{"use strict";t.exports=function(t){return"object"==typeof t&&!0===t.isAxiosError}},7985:(t,e,o)=>{"use strict";var n=o(4867);t.exports=n.isStandardBrowserEnv()?function(){var t,e=/(msie|trident)/i.test(navigator.userAgent),o=document.createElement("a");function p(t){var n=t;return e&&(o.setAttribute("href",n),n=o.href),o.setAttribute("href",n),{href:o.href,protocol:o.protocol?o.protocol.replace(/:$/,""):"",host:o.host,search:o.search?o.search.replace(/^\?/,""):"",hash:o.hash?o.hash.replace(/^#/,""):"",hostname:o.hostname,port:o.port,pathname:"/"===o.pathname.charAt(0)?o.pathname:"/"+o.pathname}}return t=p(window.location.href),function(e){var o=n.isString(e)?p(e):e;return o.protocol===t.protocol&&o.host===t.host}}():function(){return!0}},6016:(t,e,o)=>{"use strict";var n=o(4867);t.exports=function(t,e){n.forEach(t,(function(o,n){n!==e&&n.toUpperCase()===e.toUpperCase()&&(t[e]=o,delete t[n])}))}},4109:(t,e,o)=>{"use strict";var n=o(4867),p=["age","authorization","content-length","content-type","etag","expires","from","host","if-modified-since","if-unmodified-since","last-modified","location","max-forwards","proxy-authorization","referer","retry-after","user-agent"];t.exports=function(t){var e,o,b,M={};return t?(n.forEach(t.split("\n"),(function(t){if(b=t.indexOf(":"),e=n.trim(t.substr(0,b)).toLowerCase(),o=n.trim(t.substr(b+1)),e){if(M[e]&&p.indexOf(e)>=0)return;M[e]="set-cookie"===e?(M[e]?M[e]:[]).concat([o]):M[e]?M[e]+", "+o:o}})),M):M}},8713:t=>{"use strict";t.exports=function(t){return function(e){return t.apply(null,e)}}},4875:(t,e,o)=>{"use strict";var n=o(8593),p={};["object","boolean","number","function","string","symbol"].forEach((function(t,e){p[t]=function(o){return typeof o===t||"a"+(e<1?"n ":" ")+t}}));var b={},M=n.version.split(".");function z(t,e){for(var o=e?e.split("."):M,n=t.split("."),p=0;p<3;p++){if(o[p]>n[p])return!0;if(o[p]0;){var b=n[p],M=e[b];if(M){var z=t[b],r=void 0===z||M(z,b,t);if(!0!==r)throw new TypeError("option "+b+" must be "+r)}else if(!0!==o)throw Error("Unknown option "+b)}},validators:p}},4867:(t,e,o)=>{"use strict";var n=o(1849),p=Object.prototype.toString;function b(t){return"[object Array]"===p.call(t)}function M(t){return void 0===t}function z(t){return null!==t&&"object"==typeof t}function r(t){if("[object Object]"!==p.call(t))return!1;var e=Object.getPrototypeOf(t);return null===e||e===Object.prototype}function c(t){return"[object Function]"===p.call(t)}function i(t,e){if(null!=t)if("object"!=typeof t&&(t=[t]),b(t))for(var o=0,n=t.length;o{"use strict";var n=Object.freeze({}),p=Array.isArray;function b(t){return null==t}function M(t){return null!=t}function z(t){return!0===t}function r(t){return"string"==typeof t||"number"==typeof t||"symbol"==typeof t||"boolean"==typeof t}function c(t){return"function"==typeof t}function i(t){return null!==t&&"object"==typeof t}var a=Object.prototype.toString;function O(t){return"[object Object]"===a.call(t)}function s(t){return"[object RegExp]"===a.call(t)}function l(t){var e=parseFloat(String(t));return e>=0&&Math.floor(e)===e&&isFinite(t)}function d(t){return M(t)&&"function"==typeof t.then&&"function"==typeof t.catch}function u(t){return null==t?"":Array.isArray(t)||O(t)&&t.toString===a?JSON.stringify(t,null,2):String(t)}function A(t){var e=parseFloat(t);return isNaN(e)?t:e}function f(t,e){for(var o=Object.create(null),n=t.split(","),p=0;p-1)return t.splice(n,1)}}var v=Object.prototype.hasOwnProperty;function g(t,e){return v.call(t,e)}function m(t){var e=Object.create(null);return function(o){return e[o]||(e[o]=t(o))}}var R=/-(\w)/g,y=m((function(t){return t.replace(R,(function(t,e){return e?e.toUpperCase():""}))})),B=m((function(t){return t.charAt(0).toUpperCase()+t.slice(1)})),L=/\B([A-Z])/g,X=m((function(t){return t.replace(L,"-$1").toLowerCase()}));var _=Function.prototype.bind?function(t,e){return t.bind(e)}:function(t,e){function o(o){var n=arguments.length;return n?n>1?t.apply(e,arguments):t.call(e,o):t.call(e)}return o._length=t.length,o};function N(t,e){e=e||0;for(var o=t.length-e,n=new Array(o);o--;)n[o]=t[o+e];return n}function w(t,e){for(var o in e)t[o]=e[o];return t}function x(t){for(var e={},o=0;o0,et=Q&&Q.indexOf("edge/")>0;Q&&Q.indexOf("android");var ot=Q&&/iphone|ipad|ipod|ios/.test(Q);Q&&/chrome\/\d+/.test(Q),Q&&/phantomjs/.test(Q);var nt,pt=Q&&Q.match(/firefox\/(\d+)/),bt={}.watch,Mt=!1;if(K)try{var zt={};Object.defineProperty(zt,"passive",{get:function(){Mt=!0}}),window.addEventListener("test-passive",null,zt)}catch(t){}var rt=function(){return void 0===nt&&(nt=!K&&void 0!==o.g&&(o.g.process&&"server"===o.g.process.env.VUE_ENV)),nt},ct=K&&window.__VUE_DEVTOOLS_GLOBAL_HOOK__;function it(t){return"function"==typeof t&&/native code/.test(t.toString())}var at,Ot="undefined"!=typeof Symbol&&it(Symbol)&&"undefined"!=typeof Reflect&&it(Reflect.ownKeys);at="undefined"!=typeof Set&&it(Set)?Set:function(){function t(){this.set=Object.create(null)}return t.prototype.has=function(t){return!0===this.set[t]},t.prototype.add=function(t){this.set[t]=!0},t.prototype.clear=function(){this.set=Object.create(null)},t}();var st=null;function lt(t){void 0===t&&(t=null),t||st&&st._scope.off(),st=t,t&&t._scope.on()}var dt=function(){function t(t,e,o,n,p,b,M,z){this.tag=t,this.data=e,this.children=o,this.text=n,this.elm=p,this.ns=void 0,this.context=b,this.fnContext=void 0,this.fnOptions=void 0,this.fnScopeId=void 0,this.key=e&&e.key,this.componentOptions=M,this.componentInstance=void 0,this.parent=void 0,this.raw=!1,this.isStatic=!1,this.isRootInsert=!0,this.isComment=!1,this.isCloned=!1,this.isOnce=!1,this.asyncFactory=z,this.asyncMeta=void 0,this.isAsyncPlaceholder=!1}return Object.defineProperty(t.prototype,"child",{get:function(){return this.componentInstance},enumerable:!1,configurable:!0}),t}(),ut=function(t){void 0===t&&(t="");var e=new dt;return e.text=t,e.isComment=!0,e};function At(t){return new dt(void 0,void 0,void 0,String(t))}function ft(t){var e=new dt(t.tag,t.data,t.children&&t.children.slice(),t.text,t.elm,t.context,t.componentOptions,t.asyncFactory);return e.ns=t.ns,e.isStatic=t.isStatic,e.key=t.key,e.isComment=t.isComment,e.fnContext=t.fnContext,e.fnOptions=t.fnOptions,e.fnScopeId=t.fnScopeId,e.asyncMeta=t.asyncMeta,e.isCloned=!0,e}var qt=0,ht=[],Wt=function(){function t(){this._pending=!1,this.id=qt++,this.subs=[]}return t.prototype.addSub=function(t){this.subs.push(t)},t.prototype.removeSub=function(t){this.subs[this.subs.indexOf(t)]=null,this._pending||(this._pending=!0,ht.push(this))},t.prototype.depend=function(e){t.target&&t.target.addDep(this)},t.prototype.notify=function(t){var e=this.subs.filter((function(t){return t}));for(var o=0,n=e.length;o0&&(Jt((n=Kt(n,"".concat(e||"","_").concat(o)))[0])&&Jt(i)&&(a[c]=At(i.text+n[0].text),n.shift()),a.push.apply(a,n)):r(n)?Jt(i)?a[c]=At(i.text+n):""!==n&&a.push(At(n)):Jt(n)&&Jt(i)?a[c]=At(i.text+n.text):(z(t._isVList)&&M(n.tag)&&b(n.key)&&M(e)&&(n.key="__vlist".concat(e,"_").concat(o,"__")),a.push(n)));return a}function Qt(t,e,o,n,b,a){return(p(o)||r(o))&&(b=n,n=o,o=void 0),z(a)&&(b=2),function(t,e,o,n,b){if(M(o)&&M(o.__ob__))return ut();M(o)&&M(o.is)&&(e=o.is);if(!e)return ut();0;p(n)&&c(n[0])&&((o=o||{}).scopedSlots={default:n[0]},n.length=0);2===b?n=Gt(n):1===b&&(n=function(t){for(var e=0;e0,z=e?!!e.$stable:!M,r=e&&e.$key;if(e){if(e._normalized)return e._normalized;if(z&&p&&p!==n&&r===p.$key&&!M&&!p.$hasNormal)return p;for(var c in b={},e)e[c]&&"$"!==c[0]&&(b[c]=qe(t,o,c,e[c]))}else b={};for(var i in o)i in b||(b[i]=he(o,i));return e&&Object.isExtensible(e)&&(e._normalized=b),Y(b,"$stable",z),Y(b,"$key",r),Y(b,"$hasNormal",M),b}function qe(t,e,o,n){var b=function(){var e=st;lt(t);var o=arguments.length?n.apply(null,arguments):n({}),b=(o=o&&"object"==typeof o&&!p(o)?[o]:Gt(o))&&o[0];return lt(e),o&&(!b||1===o.length&&b.isComment&&!Ae(b))?void 0:o};return n.proxy&&Object.defineProperty(e,o,{get:b,enumerable:!0,configurable:!0}),b}function he(t,e){return function(){return t[e]}}function We(t){return{get attrs(){if(!t._attrsProxy){var e=t._attrsProxy={};Y(e,"_v_attr_proxy",!0),ve(e,t.$attrs,n,t,"$attrs")}return t._attrsProxy},get listeners(){t._listenersProxy||ve(t._listenersProxy={},t.$listeners,n,t,"$listeners");return t._listenersProxy},get slots(){return function(t){t._slotsProxy||me(t._slotsProxy={},t.$scopedSlots);return t._slotsProxy}(t)},emit:_(t.$emit,t),expose:function(e){e&&Object.keys(e).forEach((function(o){return Ft(t,e,o)}))}}}function ve(t,e,o,n,p){var b=!1;for(var M in e)M in t?e[M]!==o[M]&&(b=!0):(b=!0,ge(t,M,n,p));for(var M in t)M in e||(b=!0,delete t[M]);return b}function ge(t,e,o,n){Object.defineProperty(t,e,{enumerable:!0,configurable:!0,get:function(){return o[n][e]}})}function me(t,e){for(var o in e)t[o]=e[o];for(var o in t)o in e||delete t[o]}var Re,ye=null;function Be(t,e){return(t.__esModule||Ot&&"Module"===t[Symbol.toStringTag])&&(t=t.default),i(t)?e.extend(t):t}function Le(t){if(p(t))for(var e=0;edocument.createEvent("Event").timeStamp&&(Ve=function(){return $e.now()})}var Ye=function(t,e){if(t.post){if(!e.post)return 1}else if(e.post)return-1;return t.id-e.id};function Ge(){var t,e;for(Ue=Ve(),Fe=!0,De.sort(Ye),He=0;HeHe&&De[o].id>t.id;)o--;De.splice(o+1,0,t)}else De.push(t);Ie||(Ie=!0,lo(Ge))}}var Ke="watcher";"".concat(Ke," callback"),"".concat(Ke," getter"),"".concat(Ke," cleanup");var Qe;var Ze=function(){function t(t){void 0===t&&(t=!1),this.detached=t,this.active=!0,this.effects=[],this.cleanups=[],this.parent=Qe,!t&&Qe&&(this.index=(Qe.scopes||(Qe.scopes=[])).push(this)-1)}return t.prototype.run=function(t){if(this.active){var e=Qe;try{return Qe=this,t()}finally{Qe=e}}else 0},t.prototype.on=function(){Qe=this},t.prototype.off=function(){Qe=this.parent},t.prototype.stop=function(t){if(this.active){var e=void 0,o=void 0;for(e=0,o=this.effects.length;e-1)if(b&&!g(p,"default"))M=!1;else if(""===M||M===X(t)){var r=tn(String,p.type);(r<0||z-1:"string"==typeof t?t.split(",").indexOf(e)>-1:!!s(t)&&t.test(e)}function bn(t,e){var o=t.cache,n=t.keys,p=t._vnode;for(var b in o){var M=o[b];if(M){var z=M.name;z&&!e(z)&&Mn(o,b,n,p)}}}function Mn(t,e,o,n){var p=t[e];!p||n&&p.tag===n.tag||p.componentInstance.$destroy(),t[e]=null,W(o,e)}!function(t){t.prototype._init=function(t){var e=this;e._uid=No++,e._isVue=!0,e.__v_skip=!0,e._scope=new Ze(!0),e._scope._vm=!0,t&&t._isComponent?function(t,e){var o=t.$options=Object.create(t.constructor.options),n=e._parentVnode;o.parent=e.parent,o._parentVnode=n;var p=n.componentOptions;o.propsData=p.propsData,o._parentListeners=p.listeners,o._renderChildren=p.children,o._componentTag=p.tag,e.render&&(o.render=e.render,o.staticRenderFns=e.staticRenderFns)}(e,t):e.$options=Yo(wo(e.constructor),t||{},e),e._renderProxy=e,e._self=e,function(t){var e=t.$options,o=e.parent;if(o&&!e.abstract){for(;o.$options.abstract&&o.$parent;)o=o.$parent;o.$children.push(t)}t.$parent=o,t.$root=o?o.$root:t,t.$children=[],t.$refs={},t._provided=o?o._provided:Object.create(null),t._watcher=null,t._inactive=null,t._directInactive=!1,t._isMounted=!1,t._isDestroyed=!1,t._isBeingDestroyed=!1}(e),function(t){t._events=Object.create(null),t._hasHookEvent=!1;var e=t.$options._parentListeners;e&&we(t,e)}(e),function(t){t._vnode=null,t._staticTrees=null;var e=t.$options,o=t.$vnode=e._parentVnode,p=o&&o.context;t.$slots=de(e._renderChildren,p),t.$scopedSlots=o?fe(t.$parent,o.data.scopedSlots,t.$slots):n,t._c=function(e,o,n,p){return Qt(t,e,o,n,p,!1)},t.$createElement=function(e,o,n,p){return Qt(t,e,o,n,p,!0)};var b=o&&o.data;Et(t,"$attrs",b&&b.attrs||n,null,!0),Et(t,"$listeners",e._parentListeners||n,null,!0)}(e),Ee(e,"beforeCreate",void 0,!1),function(t){var e=_o(t.$options.inject,t);e&&(Tt(!1),Object.keys(e).forEach((function(o){Et(t,o,e[o])})),Tt(!0))}(e),mo(e),function(t){var e=t.$options.provide;if(e){var o=c(e)?e.call(t):e;if(!i(o))return;for(var n=to(t),p=Ot?Reflect.ownKeys(o):Object.keys(o),b=0;b1?N(o):o;for(var n=N(arguments,1),p='event handler for "'.concat(t,'"'),b=0,M=o.length;bparseInt(this.max)&&Mn(e,o[0],o,this._vnode),this.vnodeToCache=null}}},created:function(){this.cache=Object.create(null),this.keys=[]},destroyed:function(){for(var t in this.cache)Mn(this.cache,t,this.keys)},mounted:function(){var t=this;this.cacheVNode(),this.$watch("include",(function(e){bn(t,(function(t){return pn(e,t)}))})),this.$watch("exclude",(function(e){bn(t,(function(t){return!pn(e,t)}))}))},updated:function(){this.cacheVNode()},render:function(){var t=this.$slots.default,e=Le(t),o=e&&e.componentOptions;if(o){var n=nn(o),p=this.include,b=this.exclude;if(p&&(!n||!pn(p,n))||b&&n&&pn(b,n))return e;var M=this.cache,z=this.keys,r=null==e.key?o.Ctor.cid+(o.tag?"::".concat(o.tag):""):e.key;M[r]?(e.componentInstance=M[r].componentInstance,W(z,r),z.push(r)):(this.vnodeToCache=e,this.keyToCache=r),e.data.keepAlive=!0}return e||t&&t[0]}},cn={KeepAlive:rn};!function(t){var e={get:function(){return H}};Object.defineProperty(t,"config",e),t.util={warn:jo,extend:w,mergeOptions:Yo,defineReactive:Et},t.set=Dt,t.delete=Pt,t.nextTick=lo,t.observable=function(t){return kt(t),t},t.options=Object.create(null),I.forEach((function(e){t.options[e+"s"]=Object.create(null)})),t.options._base=t,w(t.options.components,cn),function(t){t.use=function(t){var e=this._installedPlugins||(this._installedPlugins=[]);if(e.indexOf(t)>-1)return this;var o=N(arguments,1);return o.unshift(this),c(t.install)?t.install.apply(t,o):c(t)&&t.apply(null,o),e.push(t),this}}(t),function(t){t.mixin=function(t){return this.options=Yo(this.options,t),this}}(t),on(t),function(t){I.forEach((function(e){t[e]=function(t,o){return o?("component"===e&&O(o)&&(o.name=o.name||t,o=this.options._base.extend(o)),"directive"===e&&c(o)&&(o={bind:o,update:o}),this.options[e+"s"][t]=o,o):this.options[e+"s"][t]}}))}(t)}(en),Object.defineProperty(en.prototype,"$isServer",{get:rt}),Object.defineProperty(en.prototype,"$ssrContext",{get:function(){return this.$vnode&&this.$vnode.ssrContext}}),Object.defineProperty(en,"FunctionalRenderContext",{value:xo}),en.version="2.7.13";var an=f("style,class"),On=f("input,textarea,option,select,progress"),sn=function(t,e,o){return"value"===o&&On(t)&&"button"!==e||"selected"===o&&"option"===t||"checked"===o&&"input"===t||"muted"===o&&"video"===t},ln=f("contenteditable,draggable,spellcheck"),dn=f("events,caret,typing,plaintext-only"),un=f("allowfullscreen,async,autofocus,autoplay,checked,compact,controls,declare,default,defaultchecked,defaultmuted,defaultselected,defer,disabled,enabled,formnovalidate,hidden,indeterminate,inert,ismap,itemscope,loop,multiple,muted,nohref,noresize,noshade,novalidate,nowrap,open,pauseonexit,readonly,required,reversed,scoped,seamless,selected,sortable,truespeed,typemustmatch,visible"),An="http://www.w3.org/1999/xlink",fn=function(t){return":"===t.charAt(5)&&"xlink"===t.slice(0,5)},qn=function(t){return fn(t)?t.slice(6,t.length):""},hn=function(t){return null==t||!1===t};function Wn(t){for(var e=t.data,o=t,n=t;M(n.componentInstance);)(n=n.componentInstance._vnode)&&n.data&&(e=vn(n.data,e));for(;M(o=o.parent);)o&&o.data&&(e=vn(e,o.data));return function(t,e){if(M(t)||M(e))return gn(t,mn(e));return""}(e.staticClass,e.class)}function vn(t,e){return{staticClass:gn(t.staticClass,e.staticClass),class:M(t.class)?[t.class,e.class]:e.class}}function gn(t,e){return t?e?t+" "+e:t:e||""}function mn(t){return Array.isArray(t)?function(t){for(var e,o="",n=0,p=t.length;n-1?Jn(t,e,o):un(e)?hn(o)?t.removeAttribute(e):(o="allowfullscreen"===e&&"EMBED"===t.tagName?"true":e,t.setAttribute(e,o)):ln(e)?t.setAttribute(e,function(t,e){return hn(e)||"false"===e?"false":"contenteditable"===t&&dn(e)?e:"true"}(e,o)):fn(e)?hn(o)?t.removeAttributeNS(An,qn(e)):t.setAttributeNS(An,e,o):Jn(t,e,o)}function Jn(t,e,o){if(hn(o))t.removeAttribute(e);else{if(Z&&!tt&&"TEXTAREA"===t.tagName&&"placeholder"===e&&""!==o&&!t.__ieph){var n=function(e){e.stopImmediatePropagation(),t.removeEventListener("input",n)};t.addEventListener("input",n),t.__ieph=!0}t.setAttribute(e,o)}}var Kn={create:Yn,update:Yn};function Qn(t,e){var o=e.elm,n=e.data,p=t.data;if(!(b(n.staticClass)&&b(n.class)&&(b(p)||b(p.staticClass)&&b(p.class)))){var z=Wn(e),r=o._transitionClasses;M(r)&&(z=gn(z,mn(r))),z!==o._prevClass&&(o.setAttribute("class",z),o._prevClass=z)}}var Zn,tp,ep,op,np,pp,bp={create:Qn,update:Qn},Mp=/[\w).+\-_$\]]/;function zp(t){var e,o,n,p,b,M=!1,z=!1,r=!1,c=!1,i=0,a=0,O=0,s=0;for(n=0;n=0&&" "===(d=t.charAt(l));l--);d&&Mp.test(d)||(c=!0)}}else void 0===p?(s=n+1,p=t.slice(0,n).trim()):u();function u(){(b||(b=[])).push(t.slice(s,n).trim()),s=n+1}if(void 0===p?p=t.slice(0,n).trim():0!==s&&u(),b)for(n=0;n-1?{exp:t.slice(0,op),key:'"'+t.slice(op+1)+'"'}:{exp:t,key:null};tp=t,op=np=pp=0;for(;!mp();)Rp(ep=gp())?Bp(ep):91===ep&&yp(ep);return{exp:t.slice(0,np),key:t.slice(np+1,pp)}}(t);return null===o.key?"".concat(t,"=").concat(e):"$set(".concat(o.exp,", ").concat(o.key,", ").concat(e,")")}function gp(){return tp.charCodeAt(++op)}function mp(){return op>=Zn}function Rp(t){return 34===t||39===t}function yp(t){var e=1;for(np=op;!mp();)if(Rp(t=gp()))Bp(t);else if(91===t&&e++,93===t&&e--,0===e){pp=op;break}}function Bp(t){for(var e=t;!mp()&&(t=gp())!==e;);}var Lp,Xp="__r";function _p(t,e,o){var n=Lp;return function p(){var b=e.apply(null,arguments);null!==b&&xp(t,p,o,n)}}var Np=Mo&&!(pt&&Number(pt[1])<=53);function wp(t,e,o,n){if(Np){var p=Ue,b=e;e=b._wrapper=function(t){if(t.target===t.currentTarget||t.timeStamp>=p||t.timeStamp<=0||t.target.ownerDocument!==document)return b.apply(this,arguments)}}Lp.addEventListener(t,e,Mt?{capture:o,passive:n}:o)}function xp(t,e,o,n){(n||Lp).removeEventListener(t,e._wrapper||e,o)}function Tp(t,e){if(!b(t.data.on)||!b(e.data.on)){var o=e.data.on||{},n=t.data.on||{};Lp=e.elm||t.elm,function(t){if(M(t.__r)){var e=Z?"change":"input";t[e]=[].concat(t.__r,t[e]||[]),delete t.__r}M(t.__c)&&(t.change=[].concat(t.__c,t.change||[]),delete t.__c)}(o),Vt(o,n,wp,xp,_p,e.context),Lp=void 0}}var Cp,Sp={create:Tp,update:Tp,destroy:function(t){return Tp(t,kn)}};function kp(t,e){if(!b(t.data.domProps)||!b(e.data.domProps)){var o,n,p=e.elm,r=t.data.domProps||{},c=e.data.domProps||{};for(o in(M(c.__ob__)||z(c._v_attr_proxy))&&(c=e.data.domProps=w({},c)),r)o in c||(p[o]="");for(o in c){if(n=c[o],"textContent"===o||"innerHTML"===o){if(e.children&&(e.children.length=0),n===r[o])continue;1===p.childNodes.length&&p.removeChild(p.childNodes[0])}if("value"===o&&"PROGRESS"!==p.tagName){p._value=n;var i=b(n)?"":String(n);Ep(p,i)&&(p.value=i)}else if("innerHTML"===o&&Bn(p.tagName)&&b(p.innerHTML)){(Cp=Cp||document.createElement("div")).innerHTML="".concat(n,"");for(var a=Cp.firstChild;p.firstChild;)p.removeChild(p.firstChild);for(;a.firstChild;)p.appendChild(a.firstChild)}else if(n!==r[o])try{p[o]=n}catch(t){}}}}function Ep(t,e){return!t.composing&&("OPTION"===t.tagName||function(t,e){var o=!0;try{o=document.activeElement!==t}catch(t){}return o&&t.value!==e}(t,e)||function(t,e){var o=t.value,n=t._vModifiers;if(M(n)){if(n.number)return A(o)!==A(e);if(n.trim)return o.trim()!==e.trim()}return o!==e}(t,e))}var Dp={create:kp,update:kp},Pp=m((function(t){var e={},o=/:(.+)/;return t.split(/;(?![^(]*\))/g).forEach((function(t){if(t){var n=t.split(o);n.length>1&&(e[n[0].trim()]=n[1].trim())}})),e}));function jp(t){var e=Ip(t.style);return t.staticStyle?w(t.staticStyle,e):e}function Ip(t){return Array.isArray(t)?x(t):"string"==typeof t?Pp(t):t}var Fp,Hp=/^--/,Up=/\s*!important$/,Vp=function(t,e,o){if(Hp.test(e))t.style.setProperty(e,o);else if(Up.test(o))t.style.setProperty(X(e),o.replace(Up,""),"important");else{var n=Yp(e);if(Array.isArray(o))for(var p=0,b=o.length;p-1?e.split(Kp).forEach((function(e){return t.classList.add(e)})):t.classList.add(e);else{var o=" ".concat(t.getAttribute("class")||""," ");o.indexOf(" "+e+" ")<0&&t.setAttribute("class",(o+e).trim())}}function Zp(t,e){if(e&&(e=e.trim()))if(t.classList)e.indexOf(" ")>-1?e.split(Kp).forEach((function(e){return t.classList.remove(e)})):t.classList.remove(e),t.classList.length||t.removeAttribute("class");else{for(var o=" ".concat(t.getAttribute("class")||""," "),n=" "+e+" ";o.indexOf(n)>=0;)o=o.replace(n," ");(o=o.trim())?t.setAttribute("class",o):t.removeAttribute("class")}}function tb(t){if(t){if("object"==typeof t){var e={};return!1!==t.css&&w(e,eb(t.name||"v")),w(e,t),e}return"string"==typeof t?eb(t):void 0}}var eb=m((function(t){return{enterClass:"".concat(t,"-enter"),enterToClass:"".concat(t,"-enter-to"),enterActiveClass:"".concat(t,"-enter-active"),leaveClass:"".concat(t,"-leave"),leaveToClass:"".concat(t,"-leave-to"),leaveActiveClass:"".concat(t,"-leave-active")}})),ob=K&&!tt,nb="transition",pb="animation",bb="transition",Mb="transitionend",zb="animation",rb="animationend";ob&&(void 0===window.ontransitionend&&void 0!==window.onwebkittransitionend&&(bb="WebkitTransition",Mb="webkitTransitionEnd"),void 0===window.onanimationend&&void 0!==window.onwebkitanimationend&&(zb="WebkitAnimation",rb="webkitAnimationEnd"));var cb=K?window.requestAnimationFrame?window.requestAnimationFrame.bind(window):setTimeout:function(t){return t()};function ib(t){cb((function(){cb(t)}))}function ab(t,e){var o=t._transitionClasses||(t._transitionClasses=[]);o.indexOf(e)<0&&(o.push(e),Qp(t,e))}function Ob(t,e){t._transitionClasses&&W(t._transitionClasses,e),Zp(t,e)}function sb(t,e,o){var n=db(t,e),p=n.type,b=n.timeout,M=n.propCount;if(!p)return o();var z=p===nb?Mb:rb,r=0,c=function(){t.removeEventListener(z,i),o()},i=function(e){e.target===t&&++r>=M&&c()};setTimeout((function(){r0&&(o=nb,i=M,a=b.length):e===pb?c>0&&(o=pb,i=c,a=r.length):a=(o=(i=Math.max(M,c))>0?M>c?nb:pb:null)?o===nb?b.length:r.length:0,{type:o,timeout:i,propCount:a,hasTransform:o===nb&&lb.test(n[bb+"Property"])}}function ub(t,e){for(;t.length1}function vb(t,e){!0!==e.data.show&&fb(e)}var gb=function(t){var e,o,n={},c=t.modules,i=t.nodeOps;for(e=0;el?h(t,b(o[A+1])?null:o[A+1].elm,o,s,A,n):s>A&&v(e,a,l)}(a,d,A,o,c):M(A)?(M(t.text)&&i.setTextContent(a,""),h(a,null,A,0,A.length-1,o)):M(d)?v(d,0,d.length-1):M(t.text)&&i.setTextContent(a,""):t.text!==e.text&&i.setTextContent(a,e.text),M(l)&&M(s=l.hook)&&M(s=s.postpatch)&&s(t,e)}}}function y(t,e,o){if(z(o)&&M(t.parent))t.parent.data.pendingInsert=e;else for(var n=0;n-1,M.selected!==b&&(M.selected=b);else if(k(Lb(M),n))return void(t.selectedIndex!==z&&(t.selectedIndex=z));p||(t.selectedIndex=-1)}}function Bb(t,e){return e.every((function(e){return!k(e,t)}))}function Lb(t){return"_value"in t?t._value:t.value}function Xb(t){t.target.composing=!0}function _b(t){t.target.composing&&(t.target.composing=!1,Nb(t.target,"input"))}function Nb(t,e){var o=document.createEvent("HTMLEvents");o.initEvent(e,!0,!0),t.dispatchEvent(o)}function wb(t){return!t.componentInstance||t.data&&t.data.transition?t:wb(t.componentInstance._vnode)}var xb={bind:function(t,e,o){var n=e.value,p=(o=wb(o)).data&&o.data.transition,b=t.__vOriginalDisplay="none"===t.style.display?"":t.style.display;n&&p?(o.data.show=!0,fb(o,(function(){t.style.display=b}))):t.style.display=n?b:"none"},update:function(t,e,o){var n=e.value;!n!=!e.oldValue&&((o=wb(o)).data&&o.data.transition?(o.data.show=!0,n?fb(o,(function(){t.style.display=t.__vOriginalDisplay})):qb(o,(function(){t.style.display="none"}))):t.style.display=n?t.__vOriginalDisplay:"none")},unbind:function(t,e,o,n,p){p||(t.style.display=t.__vOriginalDisplay)}},Tb={model:mb,show:xb},Cb={name:String,appear:Boolean,css:Boolean,mode:String,type:String,enterClass:String,leaveClass:String,enterToClass:String,leaveToClass:String,enterActiveClass:String,leaveActiveClass:String,appearClass:String,appearActiveClass:String,appearToClass:String,duration:[Number,String,Object]};function Sb(t){var e=t&&t.componentOptions;return e&&e.Ctor.options.abstract?Sb(Le(e.children)):t}function kb(t){var e={},o=t.$options;for(var n in o.propsData)e[n]=t[n];var p=o._parentListeners;for(var n in p)e[y(n)]=p[n];return e}function Eb(t,e){if(/\d-keep-alive$/.test(e.tag))return t("keep-alive",{props:e.componentOptions.propsData})}var Db=function(t){return t.tag||Ae(t)},Pb=function(t){return"show"===t.name},jb={name:"transition",props:Cb,abstract:!0,render:function(t){var e=this,o=this.$slots.default;if(o&&(o=o.filter(Db)).length){0;var n=this.mode;0;var p=o[0];if(function(t){for(;t=t.parent;)if(t.data.transition)return!0}(this.$vnode))return p;var b=Sb(p);if(!b)return p;if(this._leaving)return Eb(t,p);var M="__transition-".concat(this._uid,"-");b.key=null==b.key?b.isComment?M+"comment":M+b.tag:r(b.key)?0===String(b.key).indexOf(M)?b.key:M+b.key:b.key;var z=(b.data||(b.data={})).transition=kb(this),c=this._vnode,i=Sb(c);if(b.data.directives&&b.data.directives.some(Pb)&&(b.data.show=!0),i&&i.data&&!function(t,e){return e.key===t.key&&e.tag===t.tag}(b,i)&&!Ae(i)&&(!i.componentInstance||!i.componentInstance._vnode.isComment)){var a=i.data.transition=w({},z);if("out-in"===n)return this._leaving=!0,$t(a,"afterLeave",(function(){e._leaving=!1,e.$forceUpdate()})),Eb(t,p);if("in-out"===n){if(Ae(b))return c;var O,s=function(){O()};$t(z,"afterEnter",s),$t(z,"enterCancelled",s),$t(a,"delayLeave",(function(t){O=t}))}}return p}}},Ib=w({tag:String,moveClass:String},Cb);delete Ib.mode;var Fb={props:Ib,beforeMount:function(){var t=this,e=this._update;this._update=function(o,n){var p=Te(t);t.__patch__(t._vnode,t.kept,!1,!0),t._vnode=t.kept,p(),e.call(t,o,n)}},render:function(t){for(var e=this.tag||this.$vnode.data.tag||"span",o=Object.create(null),n=this.prevChildren=this.children,p=this.$slots.default||[],b=this.children=[],M=kb(this),z=0;z-1?_n[t]=e.constructor===window.HTMLUnknownElement||e.constructor===window.HTMLElement:_n[t]=/HTMLUnknownElement/.test(e.toString())},w(en.options.directives,Tb),w(en.options.components,$b),en.prototype.__patch__=K?gb:T,en.prototype.$mount=function(t,e){return function(t,e,o){var n;t.$el=e,t.$options.render||(t.$options.render=ut),Ee(t,"beforeMount"),n=function(){t._update(t._render(),o)},new Wo(t,n,T,{before:function(){t._isMounted&&!t._isDestroyed&&Ee(t,"beforeUpdate")}},!0),o=!1;var p=t._preWatchers;if(p)for(var b=0;b\/=]+)(?:\s*(=)\s*(?:"([^"]*)"+|'([^']*)'+|([^\s"'=<>`]+)))?/,bM=/^\s*((?:v-[\w-]+:|@|:|#)\[[^=]+?\][^\s"'<>\/=]*)(?:\s*(=)\s*(?:"([^"]*)"+|'([^']*)'+|([^\s"'=<>`]+)))?/,MM="[a-zA-Z_][\\-\\.0-9_a-zA-Z".concat(U.source,"]*"),zM="((?:".concat(MM,"\\:)?").concat(MM,")"),rM=new RegExp("^<".concat(zM)),cM=/^\s*(\/?)>/,iM=new RegExp("^<\\/".concat(zM,"[^>]*>")),aM=/^]+>/i,OM=/^",""":'"',"&":"&"," ":"\n"," ":"\t","'":"'"},AM=/&(?:lt|gt|quot|amp|#39);/g,fM=/&(?:lt|gt|quot|amp|#39|#10|#9);/g,qM=f("pre,textarea",!0),hM=function(t,e){return t&&qM(t)&&"\n"===e[0]};function WM(t,e){var o=e?fM:AM;return t.replace(o,(function(t){return uM[t]}))}function vM(t,e){for(var o,n,p=[],b=e.expectHTML,M=e.isUnaryTag||C,z=e.canBeLeftOpenTag||C,r=0,c=function(){if(o=t,n&&lM(n)){var c=0,O=n.toLowerCase(),s=dM[O]||(dM[O]=new RegExp("([\\s\\S]*?)(]*>)","i"));v=t.replace(s,(function(t,o,n){return c=n.length,lM(O)||"noscript"===O||(o=o.replace(//g,"$1").replace(//g,"$1")),hM(O,o)&&(o=o.slice(1)),e.chars&&e.chars(o),""}));r+=t.length-v.length,t=v,a(O,r-c,r)}else{var l=t.indexOf("<");if(0===l){if(OM.test(t)){var d=t.indexOf("--\x3e");if(d>=0)return e.shouldKeepComment&&e.comment&&e.comment(t.substring(4,d),r,r+d+3),i(d+3),"continue"}if(sM.test(t)){var u=t.indexOf("]>");if(u>=0)return i(u+2),"continue"}var A=t.match(aM);if(A)return i(A[0].length),"continue";var f=t.match(iM);if(f){var q=r;return i(f[0].length),a(f[1],q,r),"continue"}var h=function(){var e=t.match(rM);if(e){var o={tagName:e[1],attrs:[],start:r};i(e[0].length);for(var n=void 0,p=void 0;!(n=t.match(cM))&&(p=t.match(bM)||t.match(pM));)p.start=r,i(p[0].length),p.end=r,o.attrs.push(p);if(n)return o.unarySlash=n[1],i(n[0].length),o.end=r,o}}();if(h)return function(t){var o=t.tagName,r=t.unarySlash;b&&("p"===n&&nM(o)&&a(n),z(o)&&n===o&&a(o));for(var c=M(o)||!!r,i=t.attrs.length,O=new Array(i),s=0;s=0){for(v=t.slice(l);!(iM.test(v)||rM.test(v)||OM.test(v)||sM.test(v)||(g=v.indexOf("<",1))<0);)l+=g,v=t.slice(l);W=t.substring(0,l)}l<0&&(W=t),W&&i(W.length),e.chars&&W&&e.chars(W,r-W.length,r)}if(t===o)return e.chars&&e.chars(t),"break"};t;){if("break"===c())break}function i(e){r+=e,t=t.substring(e)}function a(t,o,b){var M,z;if(null==o&&(o=r),null==b&&(b=r),t)for(z=t.toLowerCase(),M=p.length-1;M>=0&&p[M].lowerCasedTag!==z;M--);else M=0;if(M>=0){for(var c=p.length-1;c>=M;c--)e.end&&e.end(p[c].tag,o,b);p.length=M,n=M&&p[M-1].tag}else"br"===z?e.start&&e.start(t,[],!0,o,b):"p"===z&&(e.start&&e.start(t,[],!1,o,b),e.end&&e.end(t,o,b))}a()}var gM,mM,RM,yM,BM,LM,XM,_M,NM=/^@|^v-on:/,wM=/^v-|^@|^:|^#/,xM=/([\s\S]*?)\s+(?:in|of)\s+([\s\S]*)/,TM=/,([^,\}\]]*)(?:,([^,\}\]]*))?$/,CM=/^\(|\)$/g,SM=/^\[.*\]$/,kM=/:(.*)$/,EM=/^:|^\.|^v-bind:/,DM=/\.[^.\]]+(?=[^\]]*$)/g,PM=/^v-slot(:|$)|^#/,jM=/[\r\n]/,IM=/[ \f\t\r\n]+/g,FM=m(tM),HM="_empty_";function UM(t,e,o){return{type:1,tag:t,attrsList:e,attrsMap:QM(e),rawAttrsMap:{},parent:o,children:[]}}function VM(t,e){gM=e.warn||cp,LM=e.isPreTag||C,XM=e.mustUseProp||C,_M=e.getTagNamespace||C;var o=e.isReservedTag||C;(function(t){return!(!(t.component||t.attrsMap[":is"]||t.attrsMap["v-bind:is"])&&(t.attrsMap.is?o(t.attrsMap.is):o(t.tag)))}),RM=ip(e.modules,"transformNode"),yM=ip(e.modules,"preTransformNode"),BM=ip(e.modules,"postTransformNode"),mM=e.delimiters;var n,p,b=[],M=!1!==e.preserveWhitespace,z=e.whitespace,r=!1,c=!1;function i(t){if(a(t),r||t.processed||(t=$M(t,e)),b.length||t===n||n.if&&(t.elseif||t.else)&&GM(n,{exp:t.elseif,block:t}),p&&!t.forbidden)if(t.elseif||t.else)M=t,z=function(t){for(var e=t.length;e--;){if(1===t[e].type)return t[e];t.pop()}}(p.children),z&&z.if&&GM(z,{exp:M.elseif,block:M});else{if(t.slotScope){var o=t.slotTarget||'"default"';(p.scopedSlots||(p.scopedSlots={}))[o]=t}p.children.push(t),t.parent=p}var M,z;t.children=t.children.filter((function(t){return!t.slotScope})),a(t),t.pre&&(r=!1),LM(t.tag)&&(c=!1);for(var i=0;ir&&(z.push(b=t.slice(r,p)),M.push(JSON.stringify(b)));var c=zp(n[1].trim());M.push("_s(".concat(c,")")),z.push({"@binding":c}),r=p+n[0].length}return r-1")+("true"===b?":(".concat(e,")"):":_q(".concat(e,",").concat(b,")"))),up(t,"change","var $$a=".concat(e,",")+"$$el=$event.target,"+"$$c=$$el.checked?(".concat(b,"):(").concat(M,");")+"if(Array.isArray($$a)){"+"var $$v=".concat(n?"_n("+p+")":p,",")+"$$i=_i($$a,$$v);"+"if($$el.checked){$$i<0&&(".concat(vp(e,"$$a.concat([$$v])"),")}")+"else{$$i>-1&&(".concat(vp(e,"$$a.slice(0,$$i).concat($$a.slice($$i+1))"),")}")+"}else{".concat(vp(e,"$$c"),"}"),null,!0)}(t,n,p);else if("input"===b&&"radio"===M)!function(t,e,o){var n=o&&o.number,p=Ap(t,"value")||"null";p=n?"_n(".concat(p,")"):p,ap(t,"checked","_q(".concat(e,",").concat(p,")")),up(t,"change",vp(e,p),null,!0)}(t,n,p);else if("input"===b||"textarea"===b)!function(t,e,o){var n=t.attrsMap.type;0;var p=o||{},b=p.lazy,M=p.number,z=p.trim,r=!b&&"range"!==n,c=b?"change":"range"===n?Xp:"input",i="$event.target.value";z&&(i="$event.target.value.trim()");M&&(i="_n(".concat(i,")"));var a=vp(e,i);r&&(a="if($event.target.composing)return;".concat(a));ap(t,"value","(".concat(e,")")),up(t,c,a,null,!0),(z||M)&&up(t,"blur","$forceUpdate()")}(t,n,p);else{if(!H.isReservedTag(b))return Wp(t,n,p),!1}return!0},text:function(t,e){e.value&&ap(t,"textContent","_s(".concat(e.value,")"),e)},html:function(t,e){e.value&&ap(t,"innerHTML","_s(".concat(e.value,")"),e)}},Mz={expectHTML:!0,modules:oz,directives:bz,isPreTag:function(t){return"pre"===t},isUnaryTag:eM,mustUseProp:sn,canBeLeftOpenTag:oM,isReservedTag:Ln,getTagNamespace:Xn,staticKeys:function(t){return t.reduce((function(t,e){return t.concat(e.staticKeys||[])}),[]).join(",")}(oz)},zz=m((function(t){return f("type,tag,attrsList,attrsMap,plain,parent,children,attrs,start,end,rawAttrsMap"+(t?","+t:""))}));function rz(t,e){t&&(nz=zz(e.staticKeys||""),pz=e.isReservedTag||C,cz(t),iz(t,!1))}function cz(t){if(t.static=function(t){if(2===t.type)return!1;if(3===t.type)return!0;return!(!t.pre&&(t.hasBindings||t.if||t.for||q(t.tag)||!pz(t.tag)||function(t){for(;t.parent;){if("template"!==(t=t.parent).tag)return!1;if(t.for)return!0}return!1}(t)||!Object.keys(t).every(nz)))}(t),1===t.type){if(!pz(t.tag)&&"slot"!==t.tag&&null==t.attrsMap["inline-template"])return;for(var e=0,o=t.children.length;e|^function(?:\s+[\w$]+)?\s*\(/,Oz=/\([^)]*?\);*$/,sz=/^[A-Za-z_$][\w$]*(?:\.[A-Za-z_$][\w$]*|\['[^']*?']|\["[^"]*?"]|\[\d+]|\[[A-Za-z_$][\w$]*])*$/,lz={esc:27,tab:9,enter:13,space:32,up:38,left:37,right:39,down:40,delete:[8,46]},dz={esc:["Esc","Escape"],tab:"Tab",enter:"Enter",space:[" ","Spacebar"],up:["Up","ArrowUp"],left:["Left","ArrowLeft"],right:["Right","ArrowRight"],down:["Down","ArrowDown"],delete:["Backspace","Delete","Del"]},uz=function(t){return"if(".concat(t,")return null;")},Az={stop:"$event.stopPropagation();",prevent:"$event.preventDefault();",self:uz("$event.target !== $event.currentTarget"),ctrl:uz("!$event.ctrlKey"),shift:uz("!$event.shiftKey"),alt:uz("!$event.altKey"),meta:uz("!$event.metaKey"),left:uz("'button' in $event && $event.button !== 0"),middle:uz("'button' in $event && $event.button !== 1"),right:uz("'button' in $event && $event.button !== 2")};function fz(t,e){var o=e?"nativeOn:":"on:",n="",p="";for(var b in t){var M=qz(t[b]);t[b]&&t[b].dynamic?p+="".concat(b,",").concat(M,","):n+='"'.concat(b,'":').concat(M,",")}return n="{".concat(n.slice(0,-1),"}"),p?o+"_d(".concat(n,",[").concat(p.slice(0,-1),"])"):o+n}function qz(t){if(!t)return"function(){}";if(Array.isArray(t))return"[".concat(t.map((function(t){return qz(t)})).join(","),"]");var e=sz.test(t.value),o=az.test(t.value),n=sz.test(t.value.replace(Oz,""));if(t.modifiers){var p="",b="",M=[],z=function(e){if(Az[e])b+=Az[e],lz[e]&&M.push(e);else if("exact"===e){var o=t.modifiers;b+=uz(["ctrl","shift","alt","meta"].filter((function(t){return!o[t]})).map((function(t){return"$event.".concat(t,"Key")})).join("||"))}else M.push(e)};for(var r in t.modifiers)z(r);M.length&&(p+=function(t){return"if(!$event.type.indexOf('key')&&"+"".concat(t.map(hz).join("&&"),")return null;")}(M)),b&&(p+=b);var c=e?"return ".concat(t.value,".apply(null, arguments)"):o?"return (".concat(t.value,").apply(null, arguments)"):n?"return ".concat(t.value):t.value;return"function($event){".concat(p).concat(c,"}")}return e||o?t.value:"function($event){".concat(n?"return ".concat(t.value):t.value,"}")}function hz(t){var e=parseInt(t,10);if(e)return"$event.keyCode!==".concat(e);var o=lz[t],n=dz[t];return"_k($event.keyCode,"+"".concat(JSON.stringify(t),",")+"".concat(JSON.stringify(o),",")+"$event.key,"+"".concat(JSON.stringify(n))+")"}var Wz={on:function(t,e){t.wrapListeners=function(t){return"_g(".concat(t,",").concat(e.value,")")}},bind:function(t,e){t.wrapData=function(o){return"_b(".concat(o,",'").concat(t.tag,"',").concat(e.value,",").concat(e.modifiers&&e.modifiers.prop?"true":"false").concat(e.modifiers&&e.modifiers.sync?",true":"",")")}},cloak:T},vz=function(t){this.options=t,this.warn=t.warn||cp,this.transforms=ip(t.modules,"transformCode"),this.dataGenFns=ip(t.modules,"genData"),this.directives=w(w({},Wz),t.directives);var e=t.isReservedTag||C;this.maybeComponent=function(t){return!!t.component||!e(t.tag)},this.onceId=0,this.staticRenderFns=[],this.pre=!1};function gz(t,e){var o=new vz(e),n=t?"script"===t.tag?"null":mz(t,o):'_c("div")';return{render:"with(this){return ".concat(n,"}"),staticRenderFns:o.staticRenderFns}}function mz(t,e){if(t.parent&&(t.pre=t.pre||t.parent.pre),t.staticRoot&&!t.staticProcessed)return Rz(t,e);if(t.once&&!t.onceProcessed)return yz(t,e);if(t.for&&!t.forProcessed)return Xz(t,e);if(t.if&&!t.ifProcessed)return Bz(t,e);if("template"!==t.tag||t.slotTarget||e.pre){if("slot"===t.tag)return function(t,e){var o=t.slotName||'"default"',n=xz(t,e),p="_t(".concat(o).concat(n?",function(){return ".concat(n,"}"):""),b=t.attrs||t.dynamicAttrs?Sz((t.attrs||[]).concat(t.dynamicAttrs||[]).map((function(t){return{name:y(t.name),value:t.value,dynamic:t.dynamic}}))):null,M=t.attrsMap["v-bind"];!b&&!M||n||(p+=",null");b&&(p+=",".concat(b));M&&(p+="".concat(b?"":",null",",").concat(M));return p+")"}(t,e);var o=void 0;if(t.component)o=function(t,e,o){var n=e.inlineTemplate?null:xz(e,o,!0);return"_c(".concat(t,",").concat(_z(e,o)).concat(n?",".concat(n):"",")")}(t.component,t,e);else{var n=void 0,p=e.maybeComponent(t);(!t.plain||t.pre&&p)&&(n=_z(t,e));var b=void 0,M=e.options.bindings;p&&M&&!1!==M.__isScriptSetup&&(b=function(t,e){var o=y(e),n=B(o),p=function(p){return t[e]===p?e:t[o]===p?o:t[n]===p?n:void 0},b=p("setup-const")||p("setup-reactive-const");if(b)return b;var M=p("setup-let")||p("setup-ref")||p("setup-maybe-ref");if(M)return M}(M,t.tag)),b||(b="'".concat(t.tag,"'"));var z=t.inlineTemplate?null:xz(t,e,!0);o="_c(".concat(b).concat(n?",".concat(n):"").concat(z?",".concat(z):"",")")}for(var r=0;r>>0}(M)):"",")")}(t,t.scopedSlots,e),",")),t.model&&(o+="model:{value:".concat(t.model.value,",callback:").concat(t.model.callback,",expression:").concat(t.model.expression,"},")),t.inlineTemplate){var b=function(t,e){var o=t.children[0];0;if(o&&1===o.type){var n=gz(o,e.options);return"inlineTemplate:{render:function(){".concat(n.render,"},staticRenderFns:[").concat(n.staticRenderFns.map((function(t){return"function(){".concat(t,"}")})).join(","),"]}")}}(t,e);b&&(o+="".concat(b,","))}return o=o.replace(/,$/,"")+"}",t.dynamicAttrs&&(o="_b(".concat(o,',"').concat(t.tag,'",').concat(Sz(t.dynamicAttrs),")")),t.wrapData&&(o=t.wrapData(o)),t.wrapListeners&&(o=t.wrapListeners(o)),o}function Nz(t){return 1===t.type&&("slot"===t.tag||t.children.some(Nz))}function wz(t,e){var o=t.attrsMap["slot-scope"];if(t.if&&!t.ifProcessed&&!o)return Bz(t,e,wz,"null");if(t.for&&!t.forProcessed)return Xz(t,e,wz);var n=t.slotScope===HM?"":String(t.slotScope),p="function(".concat(n,"){")+"return ".concat("template"===t.tag?t.if&&o?"(".concat(t.if,")?").concat(xz(t,e)||"undefined",":undefined"):xz(t,e)||"undefined":mz(t,e),"}"),b=n?"":",proxy:true";return"{key:".concat(t.slotTarget||'"default"',",fn:").concat(p).concat(b,"}")}function xz(t,e,o,n,p){var b=t.children;if(b.length){var M=b[0];if(1===b.length&&M.for&&"template"!==M.tag&&"slot"!==M.tag){var z=o?e.maybeComponent(M)?",1":",0":"";return"".concat((n||mz)(M,e)).concat(z)}var r=o?function(t,e){for(var o=0,n=0;n':'
',jz.innerHTML.indexOf(" ")>0}var Uz=!!K&&Hz(!1),Vz=!!K&&Hz(!0),$z=m((function(t){var e=wn(t);return e&&e.innerHTML})),Yz=en.prototype.$mount;en.prototype.$mount=function(t,e){if((t=t&&wn(t))===document.body||t===document.documentElement)return this;var o=this.$options;if(!o.render){var n=o.template;if(n)if("string"==typeof n)"#"===n.charAt(0)&&(n=$z(n));else{if(!n.nodeType)return this;n=n.innerHTML}else t&&(n=function(t){if(t.outerHTML)return t.outerHTML;var e=document.createElement("div");return e.appendChild(t.cloneNode(!0)),e.innerHTML}(t));if(n){0;var p=Fz(n,{outputSourceRange:!1,shouldDecodeNewlines:Uz,shouldDecodeNewlinesForHref:Vz,delimiters:o.delimiters,comments:o.comments},this),b=p.render,M=p.staticRenderFns;o.render=b,o.staticRenderFns=M}}return Yz.call(this,t,e)},en.compile=Fz;var Gz=o(8),Jz=o.n(Gz);const Kz={computed:{Horizon:function(t){function e(){return t.apply(this,arguments)}return e.toString=function(){return t.toString()},e}((function(){return Horizon}))},methods:{formatDate:function(t){return Jz()(1e3*t).add((new Date).getTimezoneOffset()/60)},formatDateIso:function(t){return Jz()(t).add((new Date).getTimezoneOffset()/60)},jobBaseName:function(t){if(!t.includes("\\"))return t;var e=t.split("\\");return e[e.length-1]},autoLoadNewEntries:function(){this.autoLoadsNewEntries?(this.autoLoadsNewEntries=!1,localStorage.autoLoadsNewEntries=0):(this.autoLoadsNewEntries=!0,localStorage.autoLoadsNewEntries=1)},readableTimestamp:function(t){return this.formatDate(t).format("YYYY-MM-DD HH:mm:ss")}}};var Qz=o(9669),Zz=o.n(Qz);const tr=[{path:"/",redirect:"/dashboard"},{path:"/dashboard",name:"dashboard",component:o(7124).Z},{path:"/monitoring",name:"monitoring",component:o(3317).Z},{path:"/monitoring/:tag",component:o(3343).Z,children:[{path:"jobs",name:"monitoring-jobs",component:o(4308).Z,props:{type:"jobs"}},{path:"failed",name:"monitoring-failed",component:o(4308).Z,props:{type:"failed"}}]},{path:"/metrics",redirect:"/metrics/jobs"},{path:"/metrics/",component:o(7042).Z,children:[{path:"jobs",name:"metrics-jobs",component:o(675).Z},{path:"queues",name:"metrics-queues",component:o(8947).Z}]},{path:"/metrics/:type/:slug",name:"metrics-preview",component:o(554).Z},{path:"/jobs/:type",name:"jobs",component:o(2599).Z},{path:"/jobs/pending/:jobId",name:"pending-jobs-preview",component:o(726).Z},{path:"/jobs/completed/:jobId",name:"completed-jobs-preview",component:o(726).Z},{path:"/failed",name:"failed-jobs",component:o(3741).Z},{path:"/failed/:jobId",name:"failed-jobs-preview",component:o(9594).Z},{path:"/batches",name:"batches",component:o(181).Z},{path:"/batches/:batchId",name:"batches-preview",component:o(9272).Z}];function er(t,e){for(var o in e)t[o]=e[o];return t}var or=/[!'()*]/g,nr=function(t){return"%"+t.charCodeAt(0).toString(16)},pr=/%2C/g,br=function(t){return encodeURIComponent(t).replace(or,nr).replace(pr,",")};function Mr(t){try{return decodeURIComponent(t)}catch(t){0}return t}var zr=function(t){return null==t||"object"==typeof t?t:String(t)};function rr(t){var e={};return(t=t.trim().replace(/^(\?|#|&)/,""))?(t.split("&").forEach((function(t){var o=t.replace(/\+/g," ").split("="),n=Mr(o.shift()),p=o.length>0?Mr(o.join("=")):null;void 0===e[n]?e[n]=p:Array.isArray(e[n])?e[n].push(p):e[n]=[e[n],p]})),e):e}function cr(t){var e=t?Object.keys(t).map((function(e){var o=t[e];if(void 0===o)return"";if(null===o)return br(e);if(Array.isArray(o)){var n=[];return o.forEach((function(t){void 0!==t&&(null===t?n.push(br(e)):n.push(br(e)+"="+br(t)))})),n.join("&")}return br(e)+"="+br(o)})).filter((function(t){return t.length>0})).join("&"):null;return e?"?"+e:""}var ir=/\/?$/;function ar(t,e,o,n){var p=n&&n.options.stringifyQuery,b=e.query||{};try{b=Or(b)}catch(t){}var M={name:e.name||t&&t.name,meta:t&&t.meta||{},path:e.path||"/",hash:e.hash||"",query:b,params:e.params||{},fullPath:dr(e,p),matched:t?lr(t):[]};return o&&(M.redirectedFrom=dr(o,p)),Object.freeze(M)}function Or(t){if(Array.isArray(t))return t.map(Or);if(t&&"object"==typeof t){var e={};for(var o in t)e[o]=Or(t[o]);return e}return t}var sr=ar(null,{path:"/"});function lr(t){for(var e=[];t;)e.unshift(t),t=t.parent;return e}function dr(t,e){var o=t.path,n=t.query;void 0===n&&(n={});var p=t.hash;return void 0===p&&(p=""),(o||"/")+(e||cr)(n)+p}function ur(t,e,o){return e===sr?t===e:!!e&&(t.path&&e.path?t.path.replace(ir,"")===e.path.replace(ir,"")&&(o||t.hash===e.hash&&Ar(t.query,e.query)):!(!t.name||!e.name)&&(t.name===e.name&&(o||t.hash===e.hash&&Ar(t.query,e.query)&&Ar(t.params,e.params))))}function Ar(t,e){if(void 0===t&&(t={}),void 0===e&&(e={}),!t||!e)return t===e;var o=Object.keys(t).sort(),n=Object.keys(e).sort();return o.length===n.length&&o.every((function(o,p){var b=t[o];if(n[p]!==o)return!1;var M=e[o];return null==b||null==M?b===M:"object"==typeof b&&"object"==typeof M?Ar(b,M):String(b)===String(M)}))}function fr(t){for(var e=0;e=0&&(e=t.slice(n),t=t.slice(0,n));var p=t.indexOf("?");return p>=0&&(o=t.slice(p+1),t=t.slice(0,p)),{path:t,query:o,hash:e}}(p.path||""),c=e&&e.path||"/",i=r.path?Wr(r.path,c,o||p.append):c,a=function(t,e,o){void 0===e&&(e={});var n,p=o||rr;try{n=p(t||"")}catch(t){n={}}for(var b in e){var M=e[b];n[b]=Array.isArray(M)?M.map(zr):zr(M)}return n}(r.query,p.query,n&&n.options.parseQuery),O=p.hash||r.hash;return O&&"#"!==O.charAt(0)&&(O="#"+O),{_normalized:!0,path:i,query:a,hash:O}}var Fr,Hr=function(){},Ur={name:"RouterLink",props:{to:{type:[String,Object],required:!0},tag:{type:String,default:"a"},custom:Boolean,exact:Boolean,exactPath:Boolean,append:Boolean,replace:Boolean,activeClass:String,exactActiveClass:String,ariaCurrentValue:{type:String,default:"page"},event:{type:[String,Array],default:"click"}},render:function(t){var e=this,o=this.$router,n=this.$route,p=o.resolve(this.to,n,this.append),b=p.location,M=p.route,z=p.href,r={},c=o.options.linkActiveClass,i=o.options.linkExactActiveClass,a=null==c?"router-link-active":c,O=null==i?"router-link-exact-active":i,s=null==this.activeClass?a:this.activeClass,l=null==this.exactActiveClass?O:this.exactActiveClass,d=M.redirectedFrom?ar(null,Ir(M.redirectedFrom),null,o):M;r[l]=ur(n,d,this.exactPath),r[s]=this.exact||this.exactPath?r[l]:function(t,e){return 0===t.path.replace(ir,"/").indexOf(e.path.replace(ir,"/"))&&(!e.hash||t.hash===e.hash)&&function(t,e){for(var o in e)if(!(o in t))return!1;return!0}(t.query,e.query)}(n,d);var u=r[l]?this.ariaCurrentValue:null,A=function(t){Vr(t)&&(e.replace?o.replace(b,Hr):o.push(b,Hr))},f={click:Vr};Array.isArray(this.event)?this.event.forEach((function(t){f[t]=A})):f[this.event]=A;var q={class:r},h=!this.$scopedSlots.$hasNormal&&this.$scopedSlots.default&&this.$scopedSlots.default({href:z,route:M,navigate:A,isActive:r[s],isExactActive:r[l]});if(h){if(1===h.length)return h[0];if(h.length>1||!h.length)return 0===h.length?t():t("span",{},h)}if("a"===this.tag)q.on=f,q.attrs={href:z,"aria-current":u};else{var W=$r(this.$slots.default);if(W){W.isStatic=!1;var v=W.data=er({},W.data);for(var g in v.on=v.on||{},v.on){var m=v.on[g];g in f&&(v.on[g]=Array.isArray(m)?m:[m])}for(var R in f)R in v.on?v.on[R].push(f[R]):v.on[R]=A;var y=W.data.attrs=er({},W.data.attrs);y.href=z,y["aria-current"]=u}else q.on=f}return t(this.tag,q,this.$slots.default)}};function Vr(t){if(!(t.metaKey||t.altKey||t.ctrlKey||t.shiftKey||t.defaultPrevented||void 0!==t.button&&0!==t.button)){if(t.currentTarget&&t.currentTarget.getAttribute){var e=t.currentTarget.getAttribute("target");if(/\b_blank\b/i.test(e))return}return t.preventDefault&&t.preventDefault(),!0}}function $r(t){if(t)for(var e,o=0;o-1&&(z.params[O]=o.params[O]);return z.path=jr(i.path,z.params),r(i,z,M)}if(z.path){z.params={};for(var s=0;s-1}function Rc(t,e){return mc(t)&&t._isRouter&&(null==e||t.type===e)}function yc(t,e,o){var n=function(p){p>=t.length?o():t[p]?e(t[p],(function(){n(p+1)})):n(p+1)};n(0)}function Bc(t){return function(e,o,n){var p=!1,b=0,M=null;Lc(t,(function(t,e,o,z){if("function"==typeof t&&void 0===t.cid){p=!0,b++;var r,c=Nc((function(e){var p;((p=e).__esModule||_c&&"Module"===p[Symbol.toStringTag])&&(e=e.default),t.resolved="function"==typeof e?e:Fr.extend(e),o.components[z]=e,--b<=0&&n()})),i=Nc((function(t){var e="Failed to resolve async component "+z+": "+t;M||(M=mc(t)?t:new Error(e),n(M))}));try{r=t(c,i)}catch(t){i(t)}if(r)if("function"==typeof r.then)r.then(c,i);else{var a=r.component;a&&"function"==typeof a.then&&a.then(c,i)}}})),p||n()}}function Lc(t,e){return Xc(t.map((function(t){return Object.keys(t.components).map((function(o){return e(t.components[o],t.instances[o],t,o)}))})))}function Xc(t){return Array.prototype.concat.apply([],t)}var _c="function"==typeof Symbol&&"symbol"==typeof Symbol.toStringTag;function Nc(t){var e=!1;return function(){for(var o=[],n=arguments.length;n--;)o[n]=arguments[n];if(!e)return e=!0,t.apply(this,o)}}var wc=function(t,e){this.router=t,this.base=function(t){if(!t)if(Yr){var e=document.querySelector("base");t=(t=e&&e.getAttribute("href")||"/").replace(/^https?:\/\/[^\/]+/,"")}else t="/";"/"!==t.charAt(0)&&(t="/"+t);return t.replace(/\/$/,"")}(e),this.current=sr,this.pending=null,this.ready=!1,this.readyCbs=[],this.readyErrorCbs=[],this.errorCbs=[],this.listeners=[]};function xc(t,e,o,n){var p=Lc(t,(function(t,n,p,b){var M=function(t,e){"function"!=typeof t&&(t=Fr.extend(t));return t.options[e]}(t,e);if(M)return Array.isArray(M)?M.map((function(t){return o(t,n,p,b)})):o(M,n,p,b)}));return Xc(n?p.reverse():p)}function Tc(t,e){if(e)return function(){return t.apply(e,arguments)}}wc.prototype.listen=function(t){this.cb=t},wc.prototype.onReady=function(t,e){this.ready?t():(this.readyCbs.push(t),e&&this.readyErrorCbs.push(e))},wc.prototype.onError=function(t){this.errorCbs.push(t)},wc.prototype.transitionTo=function(t,e,o){var n,p=this;try{n=this.router.match(t,this.current)}catch(t){throw this.errorCbs.forEach((function(e){e(t)})),t}var b=this.current;this.confirmTransition(n,(function(){p.updateRoute(n),e&&e(n),p.ensureURL(),p.router.afterHooks.forEach((function(t){t&&t(n,b)})),p.ready||(p.ready=!0,p.readyCbs.forEach((function(t){t(n)})))}),(function(t){o&&o(t),t&&!p.ready&&(Rc(t,qc.redirected)&&b===sr||(p.ready=!0,p.readyErrorCbs.forEach((function(e){e(t)}))))}))},wc.prototype.confirmTransition=function(t,e,o){var n=this,p=this.current;this.pending=t;var b,M,z=function(t){!Rc(t)&&mc(t)&&n.errorCbs.length&&n.errorCbs.forEach((function(e){e(t)})),o&&o(t)},r=t.matched.length-1,c=p.matched.length-1;if(ur(t,p)&&r===c&&t.matched[r]===p.matched[c])return this.ensureURL(),t.hash&&zc(this.router,p,t,!1),z(((M=vc(b=p,t,qc.duplicated,'Avoided redundant navigation to current location: "'+b.fullPath+'".')).name="NavigationDuplicated",M));var i=function(t,e){var o,n=Math.max(t.length,e.length);for(o=0;o0)){var e=this.router,o=e.options.scrollBehavior,n=uc&&o;n&&this.listeners.push(Mc());var p=function(){var o=t.current,p=Sc(t.base);t.current===sr&&p===t._startLocation||t.transitionTo(p,(function(t){n&&zc(e,t,o,!0)}))};window.addEventListener("popstate",p),this.listeners.push((function(){window.removeEventListener("popstate",p)}))}},e.prototype.go=function(t){window.history.go(t)},e.prototype.push=function(t,e,o){var n=this,p=this.current;this.transitionTo(t,(function(t){Ac(vr(n.base+t.fullPath)),zc(n.router,t,p,!1),e&&e(t)}),o)},e.prototype.replace=function(t,e,o){var n=this,p=this.current;this.transitionTo(t,(function(t){fc(vr(n.base+t.fullPath)),zc(n.router,t,p,!1),e&&e(t)}),o)},e.prototype.ensureURL=function(t){if(Sc(this.base)!==this.current.fullPath){var e=vr(this.base+this.current.fullPath);t?Ac(e):fc(e)}},e.prototype.getCurrentLocation=function(){return Sc(this.base)},e}(wc);function Sc(t){var e=window.location.pathname,o=e.toLowerCase(),n=t.toLowerCase();return!t||o!==n&&0!==o.indexOf(vr(n+"/"))||(e=e.slice(t.length)),(e||"/")+window.location.search+window.location.hash}var kc=function(t){function e(e,o,n){t.call(this,e,o),n&&function(t){var e=Sc(t);if(!/^\/#/.test(e))return window.location.replace(vr(t+"/#"+e)),!0}(this.base)||Ec()}return t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e,e.prototype.setupListeners=function(){var t=this;if(!(this.listeners.length>0)){var e=this.router.options.scrollBehavior,o=uc&&e;o&&this.listeners.push(Mc());var n=function(){var e=t.current;Ec()&&t.transitionTo(Dc(),(function(n){o&&zc(t.router,n,e,!0),uc||Ic(n.fullPath)}))},p=uc?"popstate":"hashchange";window.addEventListener(p,n),this.listeners.push((function(){window.removeEventListener(p,n)}))}},e.prototype.push=function(t,e,o){var n=this,p=this.current;this.transitionTo(t,(function(t){jc(t.fullPath),zc(n.router,t,p,!1),e&&e(t)}),o)},e.prototype.replace=function(t,e,o){var n=this,p=this.current;this.transitionTo(t,(function(t){Ic(t.fullPath),zc(n.router,t,p,!1),e&&e(t)}),o)},e.prototype.go=function(t){window.history.go(t)},e.prototype.ensureURL=function(t){var e=this.current.fullPath;Dc()!==e&&(t?jc(e):Ic(e))},e.prototype.getCurrentLocation=function(){return Dc()},e}(wc);function Ec(){var t=Dc();return"/"===t.charAt(0)||(Ic("/"+t),!1)}function Dc(){var t=window.location.href,e=t.indexOf("#");return e<0?"":t=t.slice(e+1)}function Pc(t){var e=window.location.href,o=e.indexOf("#");return(o>=0?e.slice(0,o):e)+"#"+t}function jc(t){uc?Ac(Pc(t)):window.location.hash=t}function Ic(t){uc?fc(Pc(t)):window.location.replace(Pc(t))}var Fc=function(t){function e(e,o){t.call(this,e,o),this.stack=[],this.index=-1}return t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e,e.prototype.push=function(t,e,o){var n=this;this.transitionTo(t,(function(t){n.stack=n.stack.slice(0,n.index+1).concat(t),n.index++,e&&e(t)}),o)},e.prototype.replace=function(t,e,o){var n=this;this.transitionTo(t,(function(t){n.stack=n.stack.slice(0,n.index).concat(t),e&&e(t)}),o)},e.prototype.go=function(t){var e=this,o=this.index+t;if(!(o<0||o>=this.stack.length)){var n=this.stack[o];this.confirmTransition(n,(function(){var t=e.current;e.index=o,e.updateRoute(n),e.router.afterHooks.forEach((function(e){e&&e(n,t)}))}),(function(t){Rc(t,qc.duplicated)&&(e.index=o)}))}},e.prototype.getCurrentLocation=function(){var t=this.stack[this.stack.length-1];return t?t.fullPath:"/"},e.prototype.ensureURL=function(){},e}(wc),Hc=function(t){void 0===t&&(t={}),this.app=null,this.apps=[],this.options=t,this.beforeHooks=[],this.resolveHooks=[],this.afterHooks=[],this.matcher=Qr(t.routes||[],this);var e=t.mode||"hash";switch(this.fallback="history"===e&&!uc&&!1!==t.fallback,this.fallback&&(e="hash"),Yr||(e="abstract"),this.mode=e,e){case"history":this.history=new Cc(this,t.base);break;case"hash":this.history=new kc(this,t.base,this.fallback);break;case"abstract":this.history=new Fc(this,t.base)}},Uc={currentRoute:{configurable:!0}};Hc.prototype.match=function(t,e,o){return this.matcher.match(t,e,o)},Uc.currentRoute.get=function(){return this.history&&this.history.current},Hc.prototype.init=function(t){var e=this;if(this.apps.push(t),t.$once("hook:destroyed",(function(){var o=e.apps.indexOf(t);o>-1&&e.apps.splice(o,1),e.app===t&&(e.app=e.apps[0]||null),e.app||e.history.teardown()})),!this.app){this.app=t;var o=this.history;if(o instanceof Cc||o instanceof kc){var n=function(t){o.setupListeners(),function(t){var n=o.current,p=e.options.scrollBehavior;uc&&p&&"fullPath"in t&&zc(e,t,n,!1)}(t)};o.transitionTo(o.getCurrentLocation(),n,n)}o.listen((function(t){e.apps.forEach((function(e){e._route=t}))}))}},Hc.prototype.beforeEach=function(t){return $c(this.beforeHooks,t)},Hc.prototype.beforeResolve=function(t){return $c(this.resolveHooks,t)},Hc.prototype.afterEach=function(t){return $c(this.afterHooks,t)},Hc.prototype.onReady=function(t,e){this.history.onReady(t,e)},Hc.prototype.onError=function(t){this.history.onError(t)},Hc.prototype.push=function(t,e,o){var n=this;if(!e&&!o&&"undefined"!=typeof Promise)return new Promise((function(e,o){n.history.push(t,e,o)}));this.history.push(t,e,o)},Hc.prototype.replace=function(t,e,o){var n=this;if(!e&&!o&&"undefined"!=typeof Promise)return new Promise((function(e,o){n.history.replace(t,e,o)}));this.history.replace(t,e,o)},Hc.prototype.go=function(t){this.history.go(t)},Hc.prototype.back=function(){this.go(-1)},Hc.prototype.forward=function(){this.go(1)},Hc.prototype.getMatchedComponents=function(t){var e=t?t.matched?t:this.resolve(t).route:this.currentRoute;return e?[].concat.apply([],e.matched.map((function(t){return Object.keys(t.components).map((function(e){return t.components[e]}))}))):[]},Hc.prototype.resolve=function(t,e,o){var n=Ir(t,e=e||this.history.current,o,this),p=this.match(n,e),b=p.redirectedFrom||p.fullPath,M=function(t,e,o){var n="hash"===o?"#"+e:e;return t?vr(t+"/"+n):n}(this.history.base,b,this.mode);return{location:n,route:p,href:M,normalizedTo:n,resolved:p}},Hc.prototype.getRoutes=function(){return this.matcher.getRoutes()},Hc.prototype.addRoute=function(t,e){this.matcher.addRoute(t,e),this.history.current!==sr&&this.history.transitionTo(this.history.getCurrentLocation())},Hc.prototype.addRoutes=function(t){this.matcher.addRoutes(t),this.history.current!==sr&&this.history.transitionTo(this.history.getCurrentLocation())},Object.defineProperties(Hc.prototype,Uc);var Vc=Hc;function $c(t,e){return t.push(e),function(){var o=t.indexOf(e);o>-1&&t.splice(o,1)}}Hc.install=function t(e){if(!t.installed||Fr!==e){t.installed=!0,Fr=e;var o=function(t){return void 0!==t},n=function(t,e){var n=t.$options._parentVnode;o(n)&&o(n=n.data)&&o(n=n.registerRouteInstance)&&n(t,e)};e.mixin({beforeCreate:function(){o(this.$options.router)?(this._routerRoot=this,this._router=this.$options.router,this._router.init(this),e.util.defineReactive(this,"_route",this._router.history.current)):this._routerRoot=this.$parent&&this.$parent._routerRoot||this,n(this,this)},destroyed:function(){n(this)}}),Object.defineProperty(e.prototype,"$router",{get:function(){return this._routerRoot._router}}),Object.defineProperty(e.prototype,"$route",{get:function(){return this._routerRoot._route}}),e.component("RouterView",qr),e.component("RouterLink",Ur);var p=e.config.optionMergeStrategies;p.beforeRouteEnter=p.beforeRouteLeave=p.beforeRouteUpdate=p.created}},Hc.version="3.6.5",Hc.isNavigationFailure=Rc,Hc.NavigationFailureType=qc,Hc.START_LOCATION=sr,Yr&&window.Vue&&window.Vue.use(Hc);var Yc=o(4566),Gc=o.n(Yc);window.Popper=o(8981).default;try{window.$=window.jQuery=o(9755),o(3734)}catch(t){}var Jc=document.head.querySelector('meta[name="csrf-token"]');Zz().defaults.headers.common["X-Requested-With"]="XMLHttpRequest",Jc&&(Zz().defaults.headers.common["X-CSRF-TOKEN"]=Jc.content),en.use(Vc),en.prototype.$http=Zz().create(),window.Horizon.basePath="/"+window.Horizon.path;var Kc=window.Horizon.basePath+"/";""!==window.Horizon.path&&"/"!==window.Horizon.path||(Kc="/",window.Horizon.basePath="");var Qc=new Vc({routes:tr,mode:"history",base:Kc});en.component("vue-json-pretty",Gc()),en.component("alert",o(2660).Z),en.mixin(Kz),en.directive("tooltip",(function(t,e){$(t).tooltip({title:e.value,placement:e.arg,trigger:"hover"})})),new en({el:"#horizon",router:Qc,data:function(){return{alert:{type:null,autoClose:0,message:"",confirmationProceed:null,confirmationCancel:null},autoLoadsNewEntries:"1"===localStorage.autoLoadsNewEntries}}})},3734:function(t,e,o){!function(t,e,o){"use strict";function n(t){return t&&"object"==typeof t&&"default"in t?t:{default:t}}var p=n(e),b=n(o);function M(t,e){for(var o=0;o=M)throw new Error("Bootstrap's JavaScript requires at least jQuery v1.9.1 but less than v4.0.0")}};f.jQueryDetection(),A();var q="alert",h="4.6.2",W="bs.alert",v="."+W,g=".data-api",m=p.default.fn[q],R="alert",y="fade",B="show",L="close"+v,X="closed"+v,_="click"+v+g,N='[data-dismiss="alert"]',w=function(){function t(t){this._element=t}var e=t.prototype;return e.close=function(t){var e=this._element;t&&(e=this._getRootElement(t)),this._triggerCloseEvent(e).isDefaultPrevented()||this._removeElement(e)},e.dispose=function(){p.default.removeData(this._element,W),this._element=null},e._getRootElement=function(t){var e=f.getSelectorFromElement(t),o=!1;return e&&(o=document.querySelector(e)),o||(o=p.default(t).closest("."+R)[0]),o},e._triggerCloseEvent=function(t){var e=p.default.Event(L);return p.default(t).trigger(e),e},e._removeElement=function(t){var e=this;if(p.default(t).removeClass(B),p.default(t).hasClass(y)){var o=f.getTransitionDurationFromElement(t);p.default(t).one(f.TRANSITION_END,(function(o){return e._destroyElement(t,o)})).emulateTransitionEnd(o)}else this._destroyElement(t)},e._destroyElement=function(t){p.default(t).detach().trigger(X).remove()},t._jQueryInterface=function(e){return this.each((function(){var o=p.default(this),n=o.data(W);n||(n=new t(this),o.data(W,n)),"close"===e&&n[e](this)}))},t._handleDismiss=function(t){return function(e){e&&e.preventDefault(),t.close(this)}},z(t,null,[{key:"VERSION",get:function(){return h}}]),t}();p.default(document).on(_,N,w._handleDismiss(new w)),p.default.fn[q]=w._jQueryInterface,p.default.fn[q].Constructor=w,p.default.fn[q].noConflict=function(){return p.default.fn[q]=m,w._jQueryInterface};var x="button",T="4.6.2",C="bs.button",S="."+C,k=".data-api",E=p.default.fn[x],D="active",P="btn",j="focus",I="click"+S+k,F="focus"+S+k+" blur"+S+k,H="load"+S+k,U='[data-toggle^="button"]',V='[data-toggle="buttons"]',$='[data-toggle="button"]',Y='[data-toggle="buttons"] .btn',G='input:not([type="hidden"])',J=".active",K=".btn",Q=function(){function t(t){this._element=t,this.shouldAvoidTriggerChange=!1}var e=t.prototype;return e.toggle=function(){var t=!0,e=!0,o=p.default(this._element).closest(V)[0];if(o){var n=this._element.querySelector(G);if(n){if("radio"===n.type)if(n.checked&&this._element.classList.contains(D))t=!1;else{var b=o.querySelector(J);b&&p.default(b).removeClass(D)}t&&("checkbox"!==n.type&&"radio"!==n.type||(n.checked=!this._element.classList.contains(D)),this.shouldAvoidTriggerChange||p.default(n).trigger("change")),n.focus(),e=!1}}this._element.hasAttribute("disabled")||this._element.classList.contains("disabled")||(e&&this._element.setAttribute("aria-pressed",!this._element.classList.contains(D)),t&&p.default(this._element).toggleClass(D))},e.dispose=function(){p.default.removeData(this._element,C),this._element=null},t._jQueryInterface=function(e,o){return this.each((function(){var n=p.default(this),b=n.data(C);b||(b=new t(this),n.data(C,b)),b.shouldAvoidTriggerChange=o,"toggle"===e&&b[e]()}))},z(t,null,[{key:"VERSION",get:function(){return T}}]),t}();p.default(document).on(I,U,(function(t){var e=t.target,o=e;if(p.default(e).hasClass(P)||(e=p.default(e).closest(K)[0]),!e||e.hasAttribute("disabled")||e.classList.contains("disabled"))t.preventDefault();else{var n=e.querySelector(G);if(n&&(n.hasAttribute("disabled")||n.classList.contains("disabled")))return void t.preventDefault();"INPUT"!==o.tagName&&"LABEL"===e.tagName||Q._jQueryInterface.call(p.default(e),"toggle","INPUT"===o.tagName)}})).on(F,U,(function(t){var e=p.default(t.target).closest(K)[0];p.default(e).toggleClass(j,/^focus(in)?$/.test(t.type))})),p.default(window).on(H,(function(){for(var t=[].slice.call(document.querySelectorAll(Y)),e=0,o=t.length;e0,this._pointerEvent=Boolean(window.PointerEvent||window.MSPointerEvent),this._addEventListeners()}var e=t.prototype;return e.next=function(){this._isSliding||this._slide(At)},e.nextWhenVisible=function(){var t=p.default(this._element);!document.hidden&&t.is(":visible")&&"hidden"!==t.css("visibility")&&this.next()},e.prev=function(){this._isSliding||this._slide(ft)},e.pause=function(t){t||(this._isPaused=!0),this._element.querySelector(Et)&&(f.triggerTransitionEnd(this._element),this.cycle(!0)),clearInterval(this._interval),this._interval=null},e.cycle=function(t){t||(this._isPaused=!1),this._interval&&(clearInterval(this._interval),this._interval=null),this._config.interval&&!this._isPaused&&(this._updateInterval(),this._interval=setInterval((document.visibilityState?this.nextWhenVisible:this.next).bind(this),this._config.interval))},e.to=function(t){var e=this;this._activeElement=this._element.querySelector(Ct);var o=this._getItemIndex(this._activeElement);if(!(t>this._items.length-1||t<0))if(this._isSliding)p.default(this._element).one(vt,(function(){return e.to(t)}));else{if(o===t)return this.pause(),void this.cycle();var n=t>o?At:ft;this._slide(n,this._items[t])}},e.dispose=function(){p.default(this._element).off(ot),p.default.removeData(this._element,et),this._items=null,this._config=null,this._element=null,this._interval=null,this._isPaused=null,this._isSliding=null,this._activeElement=null,this._indicatorsElement=null},e._getConfig=function(t){return t=r({},It,t),f.typeCheckConfig(Z,t,Ft),t},e._handleSwipe=function(){var t=Math.abs(this.touchDeltaX);if(!(t<=rt)){var e=t/this.touchDeltaX;this.touchDeltaX=0,e>0&&this.prev(),e<0&&this.next()}},e._addEventListeners=function(){var t=this;this._config.keyboard&&p.default(this._element).on(gt,(function(e){return t._keydown(e)})),"hover"===this._config.pause&&p.default(this._element).on(mt,(function(e){return t.pause(e)})).on(Rt,(function(e){return t.cycle(e)})),this._config.touch&&this._addTouchEventListeners()},e._addTouchEventListeners=function(){var t=this;if(this._touchSupported){var e=function(e){t._pointerEvent&&Ht[e.originalEvent.pointerType.toUpperCase()]?t.touchStartX=e.originalEvent.clientX:t._pointerEvent||(t.touchStartX=e.originalEvent.touches[0].clientX)},o=function(e){t.touchDeltaX=e.originalEvent.touches&&e.originalEvent.touches.length>1?0:e.originalEvent.touches[0].clientX-t.touchStartX},n=function(e){t._pointerEvent&&Ht[e.originalEvent.pointerType.toUpperCase()]&&(t.touchDeltaX=e.originalEvent.clientX-t.touchStartX),t._handleSwipe(),"hover"===t._config.pause&&(t.pause(),t.touchTimeout&&clearTimeout(t.touchTimeout),t.touchTimeout=setTimeout((function(e){return t.cycle(e)}),zt+t._config.interval))};p.default(this._element.querySelectorAll(kt)).on(Nt,(function(t){return t.preventDefault()})),this._pointerEvent?(p.default(this._element).on(Xt,(function(t){return e(t)})),p.default(this._element).on(_t,(function(t){return n(t)})),this._element.classList.add(ut)):(p.default(this._element).on(yt,(function(t){return e(t)})),p.default(this._element).on(Bt,(function(t){return o(t)})),p.default(this._element).on(Lt,(function(t){return n(t)})))}},e._keydown=function(t){if(!/input|textarea/i.test(t.target.tagName))switch(t.which){case bt:t.preventDefault(),this.prev();break;case Mt:t.preventDefault(),this.next()}},e._getItemIndex=function(t){return this._items=t&&t.parentNode?[].slice.call(t.parentNode.querySelectorAll(St)):[],this._items.indexOf(t)},e._getItemByDirection=function(t,e){var o=t===At,n=t===ft,p=this._getItemIndex(e),b=this._items.length-1;if((n&&0===p||o&&p===b)&&!this._config.wrap)return e;var M=(p+(t===ft?-1:1))%this._items.length;return-1===M?this._items[this._items.length-1]:this._items[M]},e._triggerSlideEvent=function(t,e){var o=this._getItemIndex(t),n=this._getItemIndex(this._element.querySelector(Ct)),b=p.default.Event(Wt,{relatedTarget:t,direction:e,from:n,to:o});return p.default(this._element).trigger(b),b},e._setActiveIndicatorElement=function(t){if(this._indicatorsElement){var e=[].slice.call(this._indicatorsElement.querySelectorAll(Tt));p.default(e).removeClass(it);var o=this._indicatorsElement.children[this._getItemIndex(t)];o&&p.default(o).addClass(it)}},e._updateInterval=function(){var t=this._activeElement||this._element.querySelector(Ct);if(t){var e=parseInt(t.getAttribute("data-interval"),10);e?(this._config.defaultInterval=this._config.defaultInterval||this._config.interval,this._config.interval=e):this._config.interval=this._config.defaultInterval||this._config.interval}},e._slide=function(t,e){var o,n,b,M=this,z=this._element.querySelector(Ct),r=this._getItemIndex(z),c=e||z&&this._getItemByDirection(t,z),i=this._getItemIndex(c),a=Boolean(this._interval);if(t===At?(o=st,n=lt,b=qt):(o=Ot,n=dt,b=ht),c&&p.default(c).hasClass(it))this._isSliding=!1;else if(!this._triggerSlideEvent(c,b).isDefaultPrevented()&&z&&c){this._isSliding=!0,a&&this.pause(),this._setActiveIndicatorElement(c),this._activeElement=c;var O=p.default.Event(vt,{relatedTarget:c,direction:b,from:r,to:i});if(p.default(this._element).hasClass(at)){p.default(c).addClass(n),f.reflow(c),p.default(z).addClass(o),p.default(c).addClass(o);var s=f.getTransitionDurationFromElement(z);p.default(z).one(f.TRANSITION_END,(function(){p.default(c).removeClass(o+" "+n).addClass(it),p.default(z).removeClass(it+" "+n+" "+o),M._isSliding=!1,setTimeout((function(){return p.default(M._element).trigger(O)}),0)})).emulateTransitionEnd(s)}else p.default(z).removeClass(it),p.default(c).addClass(it),this._isSliding=!1,p.default(this._element).trigger(O);a&&this.cycle()}},t._jQueryInterface=function(e){return this.each((function(){var o=p.default(this).data(et),n=r({},It,p.default(this).data());"object"==typeof e&&(n=r({},n,e));var b="string"==typeof e?e:n.slide;if(o||(o=new t(this,n),p.default(this).data(et,o)),"number"==typeof e)o.to(e);else if("string"==typeof b){if(void 0===o[b])throw new TypeError('No method named "'+b+'"');o[b]()}else n.interval&&n.ride&&(o.pause(),o.cycle())}))},t._dataApiClickHandler=function(e){var o=f.getSelectorFromElement(this);if(o){var n=p.default(o)[0];if(n&&p.default(n).hasClass(ct)){var b=r({},p.default(n).data(),p.default(this).data()),M=this.getAttribute("data-slide-to");M&&(b.interval=!1),t._jQueryInterface.call(p.default(n),b),M&&p.default(n).data(et).to(M),e.preventDefault()}}},z(t,null,[{key:"VERSION",get:function(){return tt}},{key:"Default",get:function(){return It}}]),t}();p.default(document).on(xt,Pt,Ut._dataApiClickHandler),p.default(window).on(wt,(function(){for(var t=[].slice.call(document.querySelectorAll(jt)),e=0,o=t.length;e0&&(this._selector=M,this._triggerArray.push(b))}this._parent=this._config.parent?this._getParent():null,this._config.parent||this._addAriaAndCollapsedClass(this._element,this._triggerArray),this._config.toggle&&this.toggle()}var e=t.prototype;return e.toggle=function(){p.default(this._element).hasClass(Qt)?this.hide():this.show()},e.show=function(){var e,o,n=this;if(!(this._isTransitioning||p.default(this._element).hasClass(Qt)||(this._parent&&0===(e=[].slice.call(this._parent.querySelectorAll(ce)).filter((function(t){return"string"==typeof n._config.parent?t.getAttribute("data-parent")===n._config.parent:t.classList.contains(Zt)}))).length&&(e=null),e&&(o=p.default(e).not(this._selector).data(Yt))&&o._isTransitioning))){var b=p.default.Event(pe);if(p.default(this._element).trigger(b),!b.isDefaultPrevented()){e&&(t._jQueryInterface.call(p.default(e).not(this._selector),"hide"),o||p.default(e).data(Yt,null));var M=this._getDimension();p.default(this._element).removeClass(Zt).addClass(te),this._element.style[M]=0,this._triggerArray.length&&p.default(this._triggerArray).removeClass(ee).attr("aria-expanded",!0),this.setTransitioning(!0);var z=function(){p.default(n._element).removeClass(te).addClass(Zt+" "+Qt),n._element.style[M]="",n.setTransitioning(!1),p.default(n._element).trigger(be)},r="scroll"+(M[0].toUpperCase()+M.slice(1)),c=f.getTransitionDurationFromElement(this._element);p.default(this._element).one(f.TRANSITION_END,z).emulateTransitionEnd(c),this._element.style[M]=this._element[r]+"px"}}},e.hide=function(){var t=this;if(!this._isTransitioning&&p.default(this._element).hasClass(Qt)){var e=p.default.Event(Me);if(p.default(this._element).trigger(e),!e.isDefaultPrevented()){var o=this._getDimension();this._element.style[o]=this._element.getBoundingClientRect()[o]+"px",f.reflow(this._element),p.default(this._element).addClass(te).removeClass(Zt+" "+Qt);var n=this._triggerArray.length;if(n>0)for(var b=0;b0},e._getOffset=function(){var t=this,e={};return"function"==typeof this._config.offset?e.fn=function(e){return e.offsets=r({},e.offsets,t._config.offset(e.offsets,t._element)),e}:e.offset=this._config.offset,e},e._getPopperConfig=function(){var t={placement:this._getPlacement(),modifiers:{offset:this._getOffset(),flip:{enabled:this._config.flip},preventOverflow:{boundariesElement:this._config.boundary}}};return"static"===this._config.display&&(t.modifiers.applyStyle={enabled:!1}),r({},t,this._config.popperConfig)},t._jQueryInterface=function(e){return this.each((function(){var o=p.default(this).data(ue);if(o||(o=new t(this,"object"==typeof e?e:null),p.default(this).data(ue,o)),"string"==typeof e){if(void 0===o[e])throw new TypeError('No method named "'+e+'"');o[e]()}}))},t._clearMenus=function(e){if(!e||e.which!==Re&&("keyup"!==e.type||e.which===ve))for(var o=[].slice.call(document.querySelectorAll(Ie)),n=0,b=o.length;n0&&M--,e.which===me&&Mdocument.documentElement.clientHeight;o||(this._element.style.overflowY="hidden"),this._element.classList.add(uo);var n=f.getTransitionDurationFromElement(this._dialog);p.default(this._element).off(f.TRANSITION_END),p.default(this._element).one(f.TRANSITION_END,(function(){t._element.classList.remove(uo),o||p.default(t._element).one(f.TRANSITION_END,(function(){t._element.style.overflowY=""})).emulateTransitionEnd(t._element,n)})).emulateTransitionEnd(n),this._element.focus()}},e._showElement=function(t){var e=this,o=p.default(this._element).hasClass(so),n=this._dialog?this._dialog.querySelector(_o):null;this._element.parentNode&&this._element.parentNode.nodeType===Node.ELEMENT_NODE||document.body.appendChild(this._element),this._element.style.display="block",this._element.removeAttribute("aria-hidden"),this._element.setAttribute("aria-modal",!0),this._element.setAttribute("role","dialog"),p.default(this._dialog).hasClass(co)&&n?n.scrollTop=0:this._element.scrollTop=0,o&&f.reflow(this._element),p.default(this._element).addClass(lo),this._config.focus&&this._enforceFocus();var b=p.default.Event(Wo,{relatedTarget:t}),M=function(){e._config.focus&&e._element.focus(),e._isTransitioning=!1,p.default(e._element).trigger(b)};if(o){var z=f.getTransitionDurationFromElement(this._dialog);p.default(this._dialog).one(f.TRANSITION_END,M).emulateTransitionEnd(z)}else M()},e._enforceFocus=function(){var t=this;p.default(document).off(vo).on(vo,(function(e){document!==e.target&&t._element!==e.target&&0===p.default(t._element).has(e.target).length&&t._element.focus()}))},e._setEscapeEvent=function(){var t=this;this._isShown?p.default(this._element).on(Ro,(function(e){t._config.keyboard&&e.which===ro?(e.preventDefault(),t.hide()):t._config.keyboard||e.which!==ro||t._triggerBackdropTransition()})):this._isShown||p.default(this._element).off(Ro)},e._setResizeEvent=function(){var t=this;this._isShown?p.default(window).on(go,(function(e){return t.handleUpdate(e)})):p.default(window).off(go)},e._hideModal=function(){var t=this;this._element.style.display="none",this._element.setAttribute("aria-hidden",!0),this._element.removeAttribute("aria-modal"),this._element.removeAttribute("role"),this._isTransitioning=!1,this._showBackdrop((function(){p.default(document.body).removeClass(Oo),t._resetAdjustments(),t._resetScrollbar(),p.default(t._element).trigger(qo)}))},e._removeBackdrop=function(){this._backdrop&&(p.default(this._backdrop).remove(),this._backdrop=null)},e._showBackdrop=function(t){var e=this,o=p.default(this._element).hasClass(so)?so:"";if(this._isShown&&this._config.backdrop){if(this._backdrop=document.createElement("div"),this._backdrop.className=ao,o&&this._backdrop.classList.add(o),p.default(this._backdrop).appendTo(document.body),p.default(this._element).on(mo,(function(t){e._ignoreBackdropClick?e._ignoreBackdropClick=!1:t.target===t.currentTarget&&("static"===e._config.backdrop?e._triggerBackdropTransition():e.hide())})),o&&f.reflow(this._backdrop),p.default(this._backdrop).addClass(lo),!t)return;if(!o)return void t();var n=f.getTransitionDurationFromElement(this._backdrop);p.default(this._backdrop).one(f.TRANSITION_END,t).emulateTransitionEnd(n)}else if(!this._isShown&&this._backdrop){p.default(this._backdrop).removeClass(lo);var b=function(){e._removeBackdrop(),t&&t()};if(p.default(this._element).hasClass(so)){var M=f.getTransitionDurationFromElement(this._backdrop);p.default(this._backdrop).one(f.TRANSITION_END,b).emulateTransitionEnd(M)}else b()}else t&&t()},e._adjustDialog=function(){var t=this._element.scrollHeight>document.documentElement.clientHeight;!this._isBodyOverflowing&&t&&(this._element.style.paddingLeft=this._scrollbarWidth+"px"),this._isBodyOverflowing&&!t&&(this._element.style.paddingRight=this._scrollbarWidth+"px")},e._resetAdjustments=function(){this._element.style.paddingLeft="",this._element.style.paddingRight=""},e._checkScrollbar=function(){var t=document.body.getBoundingClientRect();this._isBodyOverflowing=Math.round(t.left+t.right)
',trigger:"hover focus",title:"",delay:0,html:!1,selector:!1,placement:"top",offset:0,container:!1,fallbackPlacement:"flip",boundary:"scrollParent",customClass:"",sanitize:!0,sanitizeFn:null,whiteList:Do,popperConfig:null},an={animation:"boolean",template:"string",title:"(string|element|function)",trigger:"string",delay:"(number|object)",html:"boolean",selector:"(string|boolean)",placement:"(string|function)",offset:"(number|string|function)",container:"(string|element|boolean)",fallbackPlacement:"(string|array)",boundary:"(string|element)",customClass:"(string|function)",sanitize:"boolean",sanitizeFn:"(null|function)",whiteList:"object",popperConfig:"(null|object)"},On={HIDE:"hide"+$o,HIDDEN:"hidden"+$o,SHOW:"show"+$o,SHOWN:"shown"+$o,INSERTED:"inserted"+$o,CLICK:"click"+$o,FOCUSIN:"focusin"+$o,FOCUSOUT:"focusout"+$o,MOUSEENTER:"mouseenter"+$o,MOUSELEAVE:"mouseleave"+$o},sn=function(){function t(t,e){if(void 0===b.default)throw new TypeError("Bootstrap's tooltips require Popper (https://popper.js.org)");this._isEnabled=!0,this._timeout=0,this._hoverState="",this._activeTrigger={},this._popper=null,this.element=t,this.config=this._getConfig(e),this.tip=null,this._setListeners()}var e=t.prototype;return e.enable=function(){this._isEnabled=!0},e.disable=function(){this._isEnabled=!1},e.toggleEnabled=function(){this._isEnabled=!this._isEnabled},e.toggle=function(t){if(this._isEnabled)if(t){var e=this.constructor.DATA_KEY,o=p.default(t.currentTarget).data(e);o||(o=new this.constructor(t.currentTarget,this._getDelegateConfig()),p.default(t.currentTarget).data(e,o)),o._activeTrigger.click=!o._activeTrigger.click,o._isWithActiveTrigger()?o._enter(null,o):o._leave(null,o)}else{if(p.default(this.getTipElement()).hasClass(Zo))return void this._leave(null,this);this._enter(null,this)}},e.dispose=function(){clearTimeout(this._timeout),p.default.removeData(this.element,this.constructor.DATA_KEY),p.default(this.element).off(this.constructor.EVENT_KEY),p.default(this.element).closest(".modal").off("hide.bs.modal",this._hideModalHandler),this.tip&&p.default(this.tip).remove(),this._isEnabled=null,this._timeout=null,this._hoverState=null,this._activeTrigger=null,this._popper&&this._popper.destroy(),this._popper=null,this.element=null,this.config=null,this.tip=null},e.show=function(){var t=this;if("none"===p.default(this.element).css("display"))throw new Error("Please use show on visible elements");var e=p.default.Event(this.constructor.Event.SHOW);if(this.isWithContent()&&this._isEnabled){p.default(this.element).trigger(e);var o=f.findShadowRoot(this.element),n=p.default.contains(null!==o?o:this.element.ownerDocument.documentElement,this.element);if(e.isDefaultPrevented()||!n)return;var M=this.getTipElement(),z=f.getUID(this.constructor.NAME);M.setAttribute("id",z),this.element.setAttribute("aria-describedby",z),this.setContent(),this.config.animation&&p.default(M).addClass(Qo);var r="function"==typeof this.config.placement?this.config.placement.call(this,M,this.element):this.config.placement,c=this._getAttachment(r);this.addAttachmentClass(c);var i=this._getContainer();p.default(M).data(this.constructor.DATA_KEY,this),p.default.contains(this.element.ownerDocument.documentElement,this.tip)||p.default(M).appendTo(i),p.default(this.element).trigger(this.constructor.Event.INSERTED),this._popper=new b.default(this.element,M,this._getPopperConfig(c)),p.default(M).addClass(Zo),p.default(M).addClass(this.config.customClass),"ontouchstart"in document.documentElement&&p.default(document.body).children().on("mouseover",null,p.default.noop);var a=function(){t.config.animation&&t._fixTransition();var e=t._hoverState;t._hoverState=null,p.default(t.element).trigger(t.constructor.Event.SHOWN),e===en&&t._leave(null,t)};if(p.default(this.tip).hasClass(Qo)){var O=f.getTransitionDurationFromElement(this.tip);p.default(this.tip).one(f.TRANSITION_END,a).emulateTransitionEnd(O)}else a()}},e.hide=function(t){var e=this,o=this.getTipElement(),n=p.default.Event(this.constructor.Event.HIDE),b=function(){e._hoverState!==tn&&o.parentNode&&o.parentNode.removeChild(o),e._cleanTipClass(),e.element.removeAttribute("aria-describedby"),p.default(e.element).trigger(e.constructor.Event.HIDDEN),null!==e._popper&&e._popper.destroy(),t&&t()};if(p.default(this.element).trigger(n),!n.isDefaultPrevented()){if(p.default(o).removeClass(Zo),"ontouchstart"in document.documentElement&&p.default(document.body).children().off("mouseover",null,p.default.noop),this._activeTrigger[Mn]=!1,this._activeTrigger[bn]=!1,this._activeTrigger[pn]=!1,p.default(this.tip).hasClass(Qo)){var M=f.getTransitionDurationFromElement(o);p.default(o).one(f.TRANSITION_END,b).emulateTransitionEnd(M)}else b();this._hoverState=""}},e.update=function(){null!==this._popper&&this._popper.scheduleUpdate()},e.isWithContent=function(){return Boolean(this.getTitle())},e.addAttachmentClass=function(t){p.default(this.getTipElement()).addClass(Go+"-"+t)},e.getTipElement=function(){return this.tip=this.tip||p.default(this.config.template)[0],this.tip},e.setContent=function(){var t=this.getTipElement();this.setElementContent(p.default(t.querySelectorAll(on)),this.getTitle()),p.default(t).removeClass(Qo+" "+Zo)},e.setElementContent=function(t,e){"object"!=typeof e||!e.nodeType&&!e.jquery?this.config.html?(this.config.sanitize&&(e=Fo(e,this.config.whiteList,this.config.sanitizeFn)),t.html(e)):t.text(e):this.config.html?p.default(e).parent().is(t)||t.empty().append(e):t.text(p.default(e).text())},e.getTitle=function(){var t=this.element.getAttribute("data-original-title");return t||(t="function"==typeof this.config.title?this.config.title.call(this.element):this.config.title),t},e._getPopperConfig=function(t){var e=this;return r({},{placement:t,modifiers:{offset:this._getOffset(),flip:{behavior:this.config.fallbackPlacement},arrow:{element:nn},preventOverflow:{boundariesElement:this.config.boundary}},onCreate:function(t){t.originalPlacement!==t.placement&&e._handlePopperPlacementChange(t)},onUpdate:function(t){return e._handlePopperPlacementChange(t)}},this.config.popperConfig)},e._getOffset=function(){var t=this,e={};return"function"==typeof this.config.offset?e.fn=function(e){return e.offsets=r({},e.offsets,t.config.offset(e.offsets,t.element)),e}:e.offset=this.config.offset,e},e._getContainer=function(){return!1===this.config.container?document.body:f.isElement(this.config.container)?p.default(this.config.container):p.default(document).find(this.config.container)},e._getAttachment=function(t){return rn[t.toUpperCase()]},e._setListeners=function(){var t=this;this.config.trigger.split(" ").forEach((function(e){if("click"===e)p.default(t.element).on(t.constructor.Event.CLICK,t.config.selector,(function(e){return t.toggle(e)}));else if(e!==zn){var o=e===pn?t.constructor.Event.MOUSEENTER:t.constructor.Event.FOCUSIN,n=e===pn?t.constructor.Event.MOUSELEAVE:t.constructor.Event.FOCUSOUT;p.default(t.element).on(o,t.config.selector,(function(e){return t._enter(e)})).on(n,t.config.selector,(function(e){return t._leave(e)}))}})),this._hideModalHandler=function(){t.element&&t.hide()},p.default(this.element).closest(".modal").on("hide.bs.modal",this._hideModalHandler),this.config.selector?this.config=r({},this.config,{trigger:"manual",selector:""}):this._fixTitle()},e._fixTitle=function(){var t=typeof this.element.getAttribute("data-original-title");(this.element.getAttribute("title")||"string"!==t)&&(this.element.setAttribute("data-original-title",this.element.getAttribute("title")||""),this.element.setAttribute("title",""))},e._enter=function(t,e){var o=this.constructor.DATA_KEY;(e=e||p.default(t.currentTarget).data(o))||(e=new this.constructor(t.currentTarget,this._getDelegateConfig()),p.default(t.currentTarget).data(o,e)),t&&(e._activeTrigger["focusin"===t.type?bn:pn]=!0),p.default(e.getTipElement()).hasClass(Zo)||e._hoverState===tn?e._hoverState=tn:(clearTimeout(e._timeout),e._hoverState=tn,e.config.delay&&e.config.delay.show?e._timeout=setTimeout((function(){e._hoverState===tn&&e.show()}),e.config.delay.show):e.show())},e._leave=function(t,e){var o=this.constructor.DATA_KEY;(e=e||p.default(t.currentTarget).data(o))||(e=new this.constructor(t.currentTarget,this._getDelegateConfig()),p.default(t.currentTarget).data(o,e)),t&&(e._activeTrigger["focusout"===t.type?bn:pn]=!1),e._isWithActiveTrigger()||(clearTimeout(e._timeout),e._hoverState=en,e.config.delay&&e.config.delay.hide?e._timeout=setTimeout((function(){e._hoverState===en&&e.hide()}),e.config.delay.hide):e.hide())},e._isWithActiveTrigger=function(){for(var t in this._activeTrigger)if(this._activeTrigger[t])return!0;return!1},e._getConfig=function(t){var e=p.default(this.element).data();return Object.keys(e).forEach((function(t){-1!==Ko.indexOf(t)&&delete e[t]})),"number"==typeof(t=r({},this.constructor.Default,e,"object"==typeof t&&t?t:{})).delay&&(t.delay={show:t.delay,hide:t.delay}),"number"==typeof t.title&&(t.title=t.title.toString()),"number"==typeof t.content&&(t.content=t.content.toString()),f.typeCheckConfig(Ho,t,this.constructor.DefaultType),t.sanitize&&(t.template=Fo(t.template,t.whiteList,t.sanitizeFn)),t},e._getDelegateConfig=function(){var t={};if(this.config)for(var e in this.config)this.constructor.Default[e]!==this.config[e]&&(t[e]=this.config[e]);return t},e._cleanTipClass=function(){var t=p.default(this.getTipElement()),e=t.attr("class").match(Jo);null!==e&&e.length&&t.removeClass(e.join(""))},e._handlePopperPlacementChange=function(t){this.tip=t.instance.popper,this._cleanTipClass(),this.addAttachmentClass(this._getAttachment(t.placement))},e._fixTransition=function(){var t=this.getTipElement(),e=this.config.animation;null===t.getAttribute("x-placement")&&(p.default(t).removeClass(Qo),this.config.animation=!1,this.hide(),this.show(),this.config.animation=e)},t._jQueryInterface=function(e){return this.each((function(){var o=p.default(this),n=o.data(Vo),b="object"==typeof e&&e;if((n||!/dispose|hide/.test(e))&&(n||(n=new t(this,b),o.data(Vo,n)),"string"==typeof e)){if(void 0===n[e])throw new TypeError('No method named "'+e+'"');n[e]()}}))},z(t,null,[{key:"VERSION",get:function(){return Uo}},{key:"Default",get:function(){return cn}},{key:"NAME",get:function(){return Ho}},{key:"DATA_KEY",get:function(){return Vo}},{key:"Event",get:function(){return On}},{key:"EVENT_KEY",get:function(){return $o}},{key:"DefaultType",get:function(){return an}}]),t}();p.default.fn[Ho]=sn._jQueryInterface,p.default.fn[Ho].Constructor=sn,p.default.fn[Ho].noConflict=function(){return p.default.fn[Ho]=Yo,sn._jQueryInterface};var ln="popover",dn="4.6.2",un="bs.popover",An="."+un,fn=p.default.fn[ln],qn="bs-popover",hn=new RegExp("(^|\\s)"+qn+"\\S+","g"),Wn="fade",vn="show",gn=".popover-header",mn=".popover-body",Rn=r({},sn.Default,{placement:"right",trigger:"click",content:"",template:''}),yn=r({},sn.DefaultType,{content:"(string|element|function)"}),Bn={HIDE:"hide"+An,HIDDEN:"hidden"+An,SHOW:"show"+An,SHOWN:"shown"+An,INSERTED:"inserted"+An,CLICK:"click"+An,FOCUSIN:"focusin"+An,FOCUSOUT:"focusout"+An,MOUSEENTER:"mouseenter"+An,MOUSELEAVE:"mouseleave"+An},Ln=function(t){function e(){return t.apply(this,arguments)||this}c(e,t);var o=e.prototype;return o.isWithContent=function(){return this.getTitle()||this._getContent()},o.addAttachmentClass=function(t){p.default(this.getTipElement()).addClass(qn+"-"+t)},o.getTipElement=function(){return this.tip=this.tip||p.default(this.config.template)[0],this.tip},o.setContent=function(){var t=p.default(this.getTipElement());this.setElementContent(t.find(gn),this.getTitle());var e=this._getContent();"function"==typeof e&&(e=e.call(this.element)),this.setElementContent(t.find(mn),e),t.removeClass(Wn+" "+vn)},o._getContent=function(){return this.element.getAttribute("data-content")||this.config.content},o._cleanTipClass=function(){var t=p.default(this.getTipElement()),e=t.attr("class").match(hn);null!==e&&e.length>0&&t.removeClass(e.join(""))},e._jQueryInterface=function(t){return this.each((function(){var o=p.default(this).data(un),n="object"==typeof t?t:null;if((o||!/dispose|hide/.test(t))&&(o||(o=new e(this,n),p.default(this).data(un,o)),"string"==typeof t)){if(void 0===o[t])throw new TypeError('No method named "'+t+'"');o[t]()}}))},z(e,null,[{key:"VERSION",get:function(){return dn}},{key:"Default",get:function(){return Rn}},{key:"NAME",get:function(){return ln}},{key:"DATA_KEY",get:function(){return un}},{key:"Event",get:function(){return Bn}},{key:"EVENT_KEY",get:function(){return An}},{key:"DefaultType",get:function(){return yn}}]),e}(sn);p.default.fn[ln]=Ln._jQueryInterface,p.default.fn[ln].Constructor=Ln,p.default.fn[ln].noConflict=function(){return p.default.fn[ln]=fn,Ln._jQueryInterface};var Xn="scrollspy",_n="4.6.2",Nn="bs.scrollspy",wn="."+Nn,xn=".data-api",Tn=p.default.fn[Xn],Cn="dropdown-item",Sn="active",kn="activate"+wn,En="scroll"+wn,Dn="load"+wn+xn,Pn="offset",jn="position",In='[data-spy="scroll"]',Fn=".nav, .list-group",Hn=".nav-link",Un=".nav-item",Vn=".list-group-item",$n=".dropdown",Yn=".dropdown-item",Gn=".dropdown-toggle",Jn={offset:10,method:"auto",target:""},Kn={offset:"number",method:"string",target:"(string|element)"},Qn=function(){function t(t,e){var o=this;this._element=t,this._scrollElement="BODY"===t.tagName?window:t,this._config=this._getConfig(e),this._selector=this._config.target+" "+Hn+","+this._config.target+" "+Vn+","+this._config.target+" "+Yn,this._offsets=[],this._targets=[],this._activeTarget=null,this._scrollHeight=0,p.default(this._scrollElement).on(En,(function(t){return o._process(t)})),this.refresh(),this._process()}var e=t.prototype;return e.refresh=function(){var t=this,e=this._scrollElement===this._scrollElement.window?Pn:jn,o="auto"===this._config.method?e:this._config.method,n=o===jn?this._getScrollTop():0;this._offsets=[],this._targets=[],this._scrollHeight=this._getScrollHeight(),[].slice.call(document.querySelectorAll(this._selector)).map((function(t){var e,b=f.getSelectorFromElement(t);if(b&&(e=document.querySelector(b)),e){var M=e.getBoundingClientRect();if(M.width||M.height)return[p.default(e)[o]().top+n,b]}return null})).filter(Boolean).sort((function(t,e){return t[0]-e[0]})).forEach((function(e){t._offsets.push(e[0]),t._targets.push(e[1])}))},e.dispose=function(){p.default.removeData(this._element,Nn),p.default(this._scrollElement).off(wn),this._element=null,this._scrollElement=null,this._config=null,this._selector=null,this._offsets=null,this._targets=null,this._activeTarget=null,this._scrollHeight=null},e._getConfig=function(t){if("string"!=typeof(t=r({},Jn,"object"==typeof t&&t?t:{})).target&&f.isElement(t.target)){var e=p.default(t.target).attr("id");e||(e=f.getUID(Xn),p.default(t.target).attr("id",e)),t.target="#"+e}return f.typeCheckConfig(Xn,t,Kn),t},e._getScrollTop=function(){return this._scrollElement===window?this._scrollElement.pageYOffset:this._scrollElement.scrollTop},e._getScrollHeight=function(){return this._scrollElement.scrollHeight||Math.max(document.body.scrollHeight,document.documentElement.scrollHeight)},e._getOffsetHeight=function(){return this._scrollElement===window?window.innerHeight:this._scrollElement.getBoundingClientRect().height},e._process=function(){var t=this._getScrollTop()+this._config.offset,e=this._getScrollHeight(),o=this._config.offset+e-this._getOffsetHeight();if(this._scrollHeight!==e&&this.refresh(),t>=o){var n=this._targets[this._targets.length-1];this._activeTarget!==n&&this._activate(n)}else{if(this._activeTarget&&t0)return this._activeTarget=null,void this._clear();for(var p=this._offsets.length;p--;)this._activeTarget!==this._targets[p]&&t>=this._offsets[p]&&(void 0===this._offsets[p+1]||t1&&(p-=1)),[360*p,100*b,100*c]},p.rgb.hwb=function(t){var e=t[0],o=t[1],n=t[2];return[p.rgb.hsl(t)[0],1/255*Math.min(e,Math.min(o,n))*100,100*(n=1-1/255*Math.max(e,Math.max(o,n)))]},p.rgb.cmyk=function(t){var e,o=t[0]/255,n=t[1]/255,p=t[2]/255;return[100*((1-o-(e=Math.min(1-o,1-n,1-p)))/(1-e)||0),100*((1-n-e)/(1-e)||0),100*((1-p-e)/(1-e)||0),100*e]},p.rgb.keyword=function(t){var o=e[t];if(o)return o;var p,b=1/0;for(var M in n)if(n.hasOwnProperty(M)){var z=r(t,n[M]);z.04045?Math.pow((e+.055)/1.055,2.4):e/12.92)+.3576*(o=o>.04045?Math.pow((o+.055)/1.055,2.4):o/12.92)+.1805*(n=n>.04045?Math.pow((n+.055)/1.055,2.4):n/12.92)),100*(.2126*e+.7152*o+.0722*n),100*(.0193*e+.1192*o+.9505*n)]},p.rgb.lab=function(t){var e=p.rgb.xyz(t),o=e[0],n=e[1],b=e[2];return n/=100,b/=108.883,o=(o/=95.047)>.008856?Math.pow(o,1/3):7.787*o+16/116,[116*(n=n>.008856?Math.pow(n,1/3):7.787*n+16/116)-16,500*(o-n),200*(n-(b=b>.008856?Math.pow(b,1/3):7.787*b+16/116))]},p.hsl.rgb=function(t){var e,o,n,p,b,M=t[0]/360,z=t[1]/100,r=t[2]/100;if(0===z)return[b=255*r,b,b];e=2*r-(o=r<.5?r*(1+z):r+z-r*z),p=[0,0,0];for(var c=0;c<3;c++)(n=M+1/3*-(c-1))<0&&n++,n>1&&n--,b=6*n<1?e+6*(o-e)*n:2*n<1?o:3*n<2?e+(o-e)*(2/3-n)*6:e,p[c]=255*b;return p},p.hsl.hsv=function(t){var e=t[0],o=t[1]/100,n=t[2]/100,p=o,b=Math.max(n,.01);return o*=(n*=2)<=1?n:2-n,p*=b<=1?b:2-b,[e,100*(0===n?2*p/(b+p):2*o/(n+o)),(n+o)/2*100]},p.hsv.rgb=function(t){var e=t[0]/60,o=t[1]/100,n=t[2]/100,p=Math.floor(e)%6,b=e-Math.floor(e),M=255*n*(1-o),z=255*n*(1-o*b),r=255*n*(1-o*(1-b));switch(n*=255,p){case 0:return[n,r,M];case 1:return[z,n,M];case 2:return[M,n,r];case 3:return[M,z,n];case 4:return[r,M,n];case 5:return[n,M,z]}},p.hsv.hsl=function(t){var e,o,n,p=t[0],b=t[1]/100,M=t[2]/100,z=Math.max(M,.01);return n=(2-b)*M,o=b*z,[p,100*(o=(o/=(e=(2-b)*z)<=1?e:2-e)||0),100*(n/=2)]},p.hwb.rgb=function(t){var e,o,n,p,b,M,z,r=t[0]/360,c=t[1]/100,i=t[2]/100,a=c+i;switch(a>1&&(c/=a,i/=a),n=6*r-(e=Math.floor(6*r)),0!=(1&e)&&(n=1-n),p=c+n*((o=1-i)-c),e){default:case 6:case 0:b=o,M=p,z=c;break;case 1:b=p,M=o,z=c;break;case 2:b=c,M=o,z=p;break;case 3:b=c,M=p,z=o;break;case 4:b=p,M=c,z=o;break;case 5:b=o,M=c,z=p}return[255*b,255*M,255*z]},p.cmyk.rgb=function(t){var e=t[0]/100,o=t[1]/100,n=t[2]/100,p=t[3]/100;return[255*(1-Math.min(1,e*(1-p)+p)),255*(1-Math.min(1,o*(1-p)+p)),255*(1-Math.min(1,n*(1-p)+p))]},p.xyz.rgb=function(t){var e,o,n,p=t[0]/100,b=t[1]/100,M=t[2]/100;return o=-.9689*p+1.8758*b+.0415*M,n=.0557*p+-.204*b+1.057*M,e=(e=3.2406*p+-1.5372*b+-.4986*M)>.0031308?1.055*Math.pow(e,1/2.4)-.055:12.92*e,o=o>.0031308?1.055*Math.pow(o,1/2.4)-.055:12.92*o,n=n>.0031308?1.055*Math.pow(n,1/2.4)-.055:12.92*n,[255*(e=Math.min(Math.max(0,e),1)),255*(o=Math.min(Math.max(0,o),1)),255*(n=Math.min(Math.max(0,n),1))]},p.xyz.lab=function(t){var e=t[0],o=t[1],n=t[2];return o/=100,n/=108.883,e=(e/=95.047)>.008856?Math.pow(e,1/3):7.787*e+16/116,[116*(o=o>.008856?Math.pow(o,1/3):7.787*o+16/116)-16,500*(e-o),200*(o-(n=n>.008856?Math.pow(n,1/3):7.787*n+16/116))]},p.lab.xyz=function(t){var e,o,n,p=t[0];e=t[1]/500+(o=(p+16)/116),n=o-t[2]/200;var b=Math.pow(o,3),M=Math.pow(e,3),z=Math.pow(n,3);return o=b>.008856?b:(o-16/116)/7.787,e=M>.008856?M:(e-16/116)/7.787,n=z>.008856?z:(n-16/116)/7.787,[e*=95.047,o*=100,n*=108.883]},p.lab.lch=function(t){var e,o=t[0],n=t[1],p=t[2];return(e=360*Math.atan2(p,n)/2/Math.PI)<0&&(e+=360),[o,Math.sqrt(n*n+p*p),e]},p.lch.lab=function(t){var e,o=t[0],n=t[1];return e=t[2]/360*2*Math.PI,[o,n*Math.cos(e),n*Math.sin(e)]},p.rgb.ansi16=function(t){var e=t[0],o=t[1],n=t[2],b=1 in arguments?arguments[1]:p.rgb.hsv(t)[2];if(0===(b=Math.round(b/50)))return 30;var M=30+(Math.round(n/255)<<2|Math.round(o/255)<<1|Math.round(e/255));return 2===b&&(M+=60),M},p.hsv.ansi16=function(t){return p.rgb.ansi16(p.hsv.rgb(t),t[2])},p.rgb.ansi256=function(t){var e=t[0],o=t[1],n=t[2];return e===o&&o===n?e<8?16:e>248?231:Math.round((e-8)/247*24)+232:16+36*Math.round(e/255*5)+6*Math.round(o/255*5)+Math.round(n/255*5)},p.ansi16.rgb=function(t){var e=t%10;if(0===e||7===e)return t>50&&(e+=3.5),[e=e/10.5*255,e,e];var o=.5*(1+~~(t>50));return[(1&e)*o*255,(e>>1&1)*o*255,(e>>2&1)*o*255]},p.ansi256.rgb=function(t){if(t>=232){var e=10*(t-232)+8;return[e,e,e]}var o;return t-=16,[Math.floor(t/36)/5*255,Math.floor((o=t%36)/6)/5*255,o%6/5*255]},p.rgb.hex=function(t){var e=(((255&Math.round(t[0]))<<16)+((255&Math.round(t[1]))<<8)+(255&Math.round(t[2]))).toString(16).toUpperCase();return"000000".substring(e.length)+e},p.hex.rgb=function(t){var e=t.toString(16).match(/[a-f0-9]{6}|[a-f0-9]{3}/i);if(!e)return[0,0,0];var o=e[0];3===e[0].length&&(o=o.split("").map((function(t){return t+t})).join(""));var n=parseInt(o,16);return[n>>16&255,n>>8&255,255&n]},p.rgb.hcg=function(t){var e,o=t[0]/255,n=t[1]/255,p=t[2]/255,b=Math.max(Math.max(o,n),p),M=Math.min(Math.min(o,n),p),z=b-M;return e=z<=0?0:b===o?(n-p)/z%6:b===n?2+(p-o)/z:4+(o-n)/z+4,e/=6,[360*(e%=1),100*z,100*(z<1?M/(1-z):0)]},p.hsl.hcg=function(t){var e=t[1]/100,o=t[2]/100,n=1,p=0;return(n=o<.5?2*e*o:2*e*(1-o))<1&&(p=(o-.5*n)/(1-n)),[t[0],100*n,100*p]},p.hsv.hcg=function(t){var e=t[1]/100,o=t[2]/100,n=e*o,p=0;return n<1&&(p=(o-n)/(1-n)),[t[0],100*n,100*p]},p.hcg.rgb=function(t){var e=t[0]/360,o=t[1]/100,n=t[2]/100;if(0===o)return[255*n,255*n,255*n];var p=[0,0,0],b=e%1*6,M=b%1,z=1-M,r=0;switch(Math.floor(b)){case 0:p[0]=1,p[1]=M,p[2]=0;break;case 1:p[0]=z,p[1]=1,p[2]=0;break;case 2:p[0]=0,p[1]=1,p[2]=M;break;case 3:p[0]=0,p[1]=z,p[2]=1;break;case 4:p[0]=M,p[1]=0,p[2]=1;break;default:p[0]=1,p[1]=0,p[2]=z}return r=(1-o)*n,[255*(o*p[0]+r),255*(o*p[1]+r),255*(o*p[2]+r)]},p.hcg.hsv=function(t){var e=t[1]/100,o=e+t[2]/100*(1-e),n=0;return o>0&&(n=e/o),[t[0],100*n,100*o]},p.hcg.hsl=function(t){var e=t[1]/100,o=t[2]/100*(1-e)+.5*e,n=0;return o>0&&o<.5?n=e/(2*o):o>=.5&&o<1&&(n=e/(2*(1-o))),[t[0],100*n,100*o]},p.hcg.hwb=function(t){var e=t[1]/100,o=e+t[2]/100*(1-e);return[t[0],100*(o-e),100*(1-o)]},p.hwb.hcg=function(t){var e=t[1]/100,o=1-t[2]/100,n=o-e,p=0;return n<1&&(p=(o-n)/(1-n)),[t[0],100*n,100*p]},p.apple.rgb=function(t){return[t[0]/65535*255,t[1]/65535*255,t[2]/65535*255]},p.rgb.apple=function(t){return[t[0]/255*65535,t[1]/255*65535,t[2]/255*65535]},p.gray.rgb=function(t){return[t[0]/100*255,t[0]/100*255,t[0]/100*255]},p.gray.hsl=p.gray.hsv=function(t){return[0,0,t[0]]},p.gray.hwb=function(t){return[0,100,t[0]]},p.gray.cmyk=function(t){return[0,0,0,t[0]]},p.gray.lab=function(t){return[t[0],0,0]},p.gray.hex=function(t){var e=255&Math.round(t[0]/100*255),o=((e<<16)+(e<<8)+e).toString(16).toUpperCase();return"000000".substring(o.length)+o},p.rgb.gray=function(t){return[(t[0]+t[1]+t[2])/3/255*100]}}));function b(){for(var t={},e=Object.keys(p),o=e.length,n=0;n1&&(e=Array.prototype.slice.call(arguments)),t(e))};return"conversion"in t&&(e.conversion=t.conversion),e}function O(t){var e=function(e){if(null==e)return e;arguments.length>1&&(e=Array.prototype.slice.call(arguments));var o=t(e);if("object"==typeof o)for(var n=o.length,p=0;p=0&&e<1?w(Math.round(255*e)):"")}function g(t,e){return e<1||t[3]&&t[3]<1?m(t,e):"rgb("+t[0]+", "+t[1]+", "+t[2]+")"}function m(t,e){return void 0===e&&(e=void 0!==t[3]?t[3]:1),"rgba("+t[0]+", "+t[1]+", "+t[2]+", "+e+")"}function R(t,e){return e<1||t[3]&&t[3]<1?y(t,e):"rgb("+Math.round(t[0]/255*100)+"%, "+Math.round(t[1]/255*100)+"%, "+Math.round(t[2]/255*100)+"%)"}function y(t,e){return"rgba("+Math.round(t[0]/255*100)+"%, "+Math.round(t[1]/255*100)+"%, "+Math.round(t[2]/255*100)+"%, "+(e||t[3]||1)+")"}function B(t,e){return e<1||t[3]&&t[3]<1?L(t,e):"hsl("+t[0]+", "+t[1]+"%, "+t[2]+"%)"}function L(t,e){return void 0===e&&(e=void 0!==t[3]?t[3]:1),"hsla("+t[0]+", "+t[1]+"%, "+t[2]+"%, "+e+")"}function X(t,e){return void 0===e&&(e=void 0!==t[3]?t[3]:1),"hwb("+t[0]+", "+t[1]+"%, "+t[2]+"%"+(void 0!==e&&1!==e?", "+e:"")+")"}function _(t){return x[t.slice(0,3)]}function N(t,e,o){return Math.min(Math.max(e,t),o)}function w(t){var e=t.toString(16).toUpperCase();return e.length<2?"0"+e:e}var x={};for(var T in l)x[l[T]]=T;var C=function(t){return t instanceof C?t:this instanceof C?(this.valid=!1,this.values={rgb:[0,0,0],hsl:[0,0,0],hsv:[0,0,0],hwb:[0,0,0],cmyk:[0,0,0,0],alpha:1},void("string"==typeof t?(e=d.getRgba(t))?this.setValues("rgb",e):(e=d.getHsla(t))?this.setValues("hsl",e):(e=d.getHwb(t))&&this.setValues("hwb",e):"object"==typeof t&&(void 0!==(e=t).r||void 0!==e.red?this.setValues("rgb",e):void 0!==e.l||void 0!==e.lightness?this.setValues("hsl",e):void 0!==e.v||void 0!==e.value?this.setValues("hsv",e):void 0!==e.w||void 0!==e.whiteness?this.setValues("hwb",e):void 0===e.c&&void 0===e.cyan||this.setValues("cmyk",e)))):new C(t);var e};C.prototype={isValid:function(){return this.valid},rgb:function(){return this.setSpace("rgb",arguments)},hsl:function(){return this.setSpace("hsl",arguments)},hsv:function(){return this.setSpace("hsv",arguments)},hwb:function(){return this.setSpace("hwb",arguments)},cmyk:function(){return this.setSpace("cmyk",arguments)},rgbArray:function(){return this.values.rgb},hslArray:function(){return this.values.hsl},hsvArray:function(){return this.values.hsv},hwbArray:function(){var t=this.values;return 1!==t.alpha?t.hwb.concat([t.alpha]):t.hwb},cmykArray:function(){return this.values.cmyk},rgbaArray:function(){var t=this.values;return t.rgb.concat([t.alpha])},hslaArray:function(){var t=this.values;return t.hsl.concat([t.alpha])},alpha:function(t){return void 0===t?this.values.alpha:(this.setValues("alpha",t),this)},red:function(t){return this.setChannel("rgb",0,t)},green:function(t){return this.setChannel("rgb",1,t)},blue:function(t){return this.setChannel("rgb",2,t)},hue:function(t){return t&&(t=(t%=360)<0?360+t:t),this.setChannel("hsl",0,t)},saturation:function(t){return this.setChannel("hsl",1,t)},lightness:function(t){return this.setChannel("hsl",2,t)},saturationv:function(t){return this.setChannel("hsv",1,t)},whiteness:function(t){return this.setChannel("hwb",1,t)},blackness:function(t){return this.setChannel("hwb",2,t)},value:function(t){return this.setChannel("hsv",2,t)},cyan:function(t){return this.setChannel("cmyk",0,t)},magenta:function(t){return this.setChannel("cmyk",1,t)},yellow:function(t){return this.setChannel("cmyk",2,t)},black:function(t){return this.setChannel("cmyk",3,t)},hexString:function(){return d.hexString(this.values.rgb)},rgbString:function(){return d.rgbString(this.values.rgb,this.values.alpha)},rgbaString:function(){return d.rgbaString(this.values.rgb,this.values.alpha)},percentString:function(){return d.percentString(this.values.rgb,this.values.alpha)},hslString:function(){return d.hslString(this.values.hsl,this.values.alpha)},hslaString:function(){return d.hslaString(this.values.hsl,this.values.alpha)},hwbString:function(){return d.hwbString(this.values.hwb,this.values.alpha)},keyword:function(){return d.keyword(this.values.rgb,this.values.alpha)},rgbNumber:function(){var t=this.values.rgb;return t[0]<<16|t[1]<<8|t[2]},luminosity:function(){for(var t=this.values.rgb,e=[],o=0;oo?(e+.05)/(o+.05):(o+.05)/(e+.05)},level:function(t){var e=this.contrast(t);return e>=7.1?"AAA":e>=4.5?"AA":""},dark:function(){var t=this.values.rgb;return(299*t[0]+587*t[1]+114*t[2])/1e3<128},light:function(){return!this.dark()},negate:function(){for(var t=[],e=0;e<3;e++)t[e]=255-this.values.rgb[e];return this.setValues("rgb",t),this},lighten:function(t){var e=this.values.hsl;return e[2]+=e[2]*t,this.setValues("hsl",e),this},darken:function(t){var e=this.values.hsl;return e[2]-=e[2]*t,this.setValues("hsl",e),this},saturate:function(t){var e=this.values.hsl;return e[1]+=e[1]*t,this.setValues("hsl",e),this},desaturate:function(t){var e=this.values.hsl;return e[1]-=e[1]*t,this.setValues("hsl",e),this},whiten:function(t){var e=this.values.hwb;return e[1]+=e[1]*t,this.setValues("hwb",e),this},blacken:function(t){var e=this.values.hwb;return e[2]+=e[2]*t,this.setValues("hwb",e),this},greyscale:function(){var t=this.values.rgb,e=.3*t[0]+.59*t[1]+.11*t[2];return this.setValues("rgb",[e,e,e]),this},clearer:function(t){var e=this.values.alpha;return this.setValues("alpha",e-e*t),this},opaquer:function(t){var e=this.values.alpha;return this.setValues("alpha",e+e*t),this},rotate:function(t){var e=this.values.hsl,o=(e[0]+t)%360;return e[0]=o<0?360+o:o,this.setValues("hsl",e),this},mix:function(t,e){var o=this,n=t,p=void 0===e?.5:e,b=2*p-1,M=o.alpha()-n.alpha(),z=((b*M==-1?b:(b+M)/(1+b*M))+1)/2,r=1-z;return this.rgb(z*o.red()+r*n.red(),z*o.green()+r*n.green(),z*o.blue()+r*n.blue()).alpha(o.alpha()*p+n.alpha()*(1-p))},toJSON:function(){return this.rgb()},clone:function(){var t,e,o=new C,n=this.values,p=o.values;for(var b in n)n.hasOwnProperty(b)&&(t=n[b],"[object Array]"===(e={}.toString.call(t))?p[b]=t.slice(0):"[object Number]"===e&&(p[b]=t));return o}},C.prototype.spaces={rgb:["red","green","blue"],hsl:["hue","saturation","lightness"],hsv:["hue","saturation","value"],hwb:["hue","whiteness","blackness"],cmyk:["cyan","magenta","yellow","black"]},C.prototype.maxes={rgb:[255,255,255],hsl:[360,100,100],hsv:[360,100,100],hwb:[360,100,100],cmyk:[100,100,100,100]},C.prototype.getValues=function(t){for(var e=this.values,o={},n=0;n=0;p--)e.call(o,t[p],p);else for(p=0;p=1?t:-(Math.sqrt(1-t*t)-1)},easeOutCirc:function(t){return Math.sqrt(1-(t-=1)*t)},easeInOutCirc:function(t){return(t/=.5)<1?-.5*(Math.sqrt(1-t*t)-1):.5*(Math.sqrt(1-(t-=2)*t)+1)},easeInElastic:function(t){var e=1.70158,o=0,n=1;return 0===t?0:1===t?1:(o||(o=.3),n<1?(n=1,e=o/4):e=o/(2*Math.PI)*Math.asin(1/n),-n*Math.pow(2,10*(t-=1))*Math.sin((t-e)*(2*Math.PI)/o))},easeOutElastic:function(t){var e=1.70158,o=0,n=1;return 0===t?0:1===t?1:(o||(o=.3),n<1?(n=1,e=o/4):e=o/(2*Math.PI)*Math.asin(1/n),n*Math.pow(2,-10*t)*Math.sin((t-e)*(2*Math.PI)/o)+1)},easeInOutElastic:function(t){var e=1.70158,o=0,n=1;return 0===t?0:2==(t/=.5)?1:(o||(o=.45),n<1?(n=1,e=o/4):e=o/(2*Math.PI)*Math.asin(1/n),t<1?n*Math.pow(2,10*(t-=1))*Math.sin((t-e)*(2*Math.PI)/o)*-.5:n*Math.pow(2,-10*(t-=1))*Math.sin((t-e)*(2*Math.PI)/o)*.5+1)},easeInBack:function(t){var e=1.70158;return t*t*((e+1)*t-e)},easeOutBack:function(t){var e=1.70158;return(t-=1)*t*((e+1)*t+e)+1},easeInOutBack:function(t){var e=1.70158;return(t/=.5)<1?t*t*((1+(e*=1.525))*t-e)*.5:.5*((t-=2)*t*((1+(e*=1.525))*t+e)+2)},easeInBounce:function(t){return 1-j.easeOutBounce(1-t)},easeOutBounce:function(t){return t<1/2.75?7.5625*t*t:t<2/2.75?7.5625*(t-=1.5/2.75)*t+.75:t<2.5/2.75?7.5625*(t-=2.25/2.75)*t+.9375:7.5625*(t-=2.625/2.75)*t+.984375},easeInOutBounce:function(t){return t<.5?.5*j.easeInBounce(2*t):.5*j.easeOutBounce(2*t-1)+.5}},I={effects:j};P.easingEffects=j;var F=Math.PI,H=F/180,U=2*F,V=F/2,$=F/4,Y=2*F/3,G={clear:function(t){t.ctx.clearRect(0,0,t.width,t.height)},roundedRect:function(t,e,o,n,p,b){if(b){var M=Math.min(b,p/2,n/2),z=e+M,r=o+M,c=e+n-M,i=o+p-M;t.moveTo(e,r),ze.left-o&&t.xe.top-o&&t.y0&&t.requestAnimationFrame()},advance:function(){for(var t,e,o,n,p=this.animations,b=0;b=o?(zt.callback(t.onAnimationComplete,[t],e),e.animating=!1,p.splice(b,1)):++b}},qt=zt.options.resolve,ht=["push","pop","shift","splice","unshift"];function Wt(t,e){t._chartjs?t._chartjs.listeners.push(e):(Object.defineProperty(t,"_chartjs",{configurable:!0,enumerable:!1,value:{listeners:[e]}}),ht.forEach((function(e){var o="onData"+e.charAt(0).toUpperCase()+e.slice(1),n=t[e];Object.defineProperty(t,e,{configurable:!0,enumerable:!1,value:function(){var e=Array.prototype.slice.call(arguments),p=n.apply(this,e);return zt.each(t._chartjs.listeners,(function(t){"function"==typeof t[o]&&t[o].apply(t,e)})),p}})})))}function vt(t,e){var o=t._chartjs;if(o){var n=o.listeners,p=n.indexOf(e);-1!==p&&n.splice(p,1),n.length>0||(ht.forEach((function(e){delete t[e]})),delete t._chartjs)}}var gt=function(t,e){this.initialize(t,e)};zt.extend(gt.prototype,{datasetElementType:null,dataElementType:null,_datasetElementOptions:["backgroundColor","borderCapStyle","borderColor","borderDash","borderDashOffset","borderJoinStyle","borderWidth"],_dataElementOptions:["backgroundColor","borderColor","borderWidth","pointStyle"],initialize:function(t,e){var o=this;o.chart=t,o.index=e,o.linkScales(),o.addElements(),o._type=o.getMeta().type},updateIndex:function(t){this.index=t},linkScales:function(){var t=this,e=t.getMeta(),o=t.chart,n=o.scales,p=t.getDataset(),b=o.options.scales;null!==e.xAxisID&&e.xAxisID in n&&!p.xAxisID||(e.xAxisID=p.xAxisID||b.xAxes[0].id),null!==e.yAxisID&&e.yAxisID in n&&!p.yAxisID||(e.yAxisID=p.yAxisID||b.yAxes[0].id)},getDataset:function(){return this.chart.data.datasets[this.index]},getMeta:function(){return this.chart.getDatasetMeta(this.index)},getScaleForId:function(t){return this.chart.scales[t]},_getValueScaleId:function(){return this.getMeta().yAxisID},_getIndexScaleId:function(){return this.getMeta().xAxisID},_getValueScale:function(){return this.getScaleForId(this._getValueScaleId())},_getIndexScale:function(){return this.getScaleForId(this._getIndexScaleId())},reset:function(){this._update(!0)},destroy:function(){this._data&&vt(this._data,this)},createMetaDataset:function(){var t=this,e=t.datasetElementType;return e&&new e({_chart:t.chart,_datasetIndex:t.index})},createMetaData:function(t){var e=this,o=e.dataElementType;return o&&new o({_chart:e.chart,_datasetIndex:e.index,_index:t})},addElements:function(){var t,e,o=this,n=o.getMeta(),p=o.getDataset().data||[],b=n.data;for(t=0,e=p.length;tn&&t.insertElements(n,p-n)},insertElements:function(t,e){for(var o=0;op?(b=p/e.innerRadius,t.arc(M,z,e.innerRadius-p,n+b,o-b,!0)):t.arc(M,z,p,n+Math.PI/2,o-Math.PI/2),t.closePath(),t.clip()}function Bt(t,e,o,n){var p,b=o.endAngle;for(n&&(o.endAngle=o.startAngle+Rt,yt(t,o),o.endAngle=b,o.endAngle===o.startAngle&&o.fullCircles&&(o.endAngle+=Rt,o.fullCircles--)),t.beginPath(),t.arc(o.x,o.y,o.innerRadius,o.startAngle+Rt,o.startAngle,!0),p=0;pz;)p-=Rt;for(;p=M&&p<=z,c=b>=o.innerRadius&&b<=o.outerRadius;return r&&c}return!1},getCenterPoint:function(){var t=this._view,e=(t.startAngle+t.endAngle)/2,o=(t.innerRadius+t.outerRadius)/2;return{x:t.x+Math.cos(e)*o,y:t.y+Math.sin(e)*o}},getArea:function(){var t=this._view;return Math.PI*((t.endAngle-t.startAngle)/(2*Math.PI))*(Math.pow(t.outerRadius,2)-Math.pow(t.innerRadius,2))},tooltipPosition:function(){var t=this._view,e=t.startAngle+(t.endAngle-t.startAngle)/2,o=(t.outerRadius-t.innerRadius)/2+t.innerRadius;return{x:t.x+Math.cos(e)*o,y:t.y+Math.sin(e)*o}},draw:function(){var t,e=this._chart.ctx,o=this._view,n="inner"===o.borderAlign?.33:0,p={x:o.x,y:o.y,innerRadius:o.innerRadius,outerRadius:Math.max(o.outerRadius-n,0),pixelMargin:n,startAngle:o.startAngle,endAngle:o.endAngle,fullCircles:Math.floor(o.circumference/Rt)};if(e.save(),e.fillStyle=o.backgroundColor,e.strokeStyle=o.borderColor,p.fullCircles){for(p.endAngle=p.startAngle+Rt,e.beginPath(),e.arc(p.x,p.y,p.outerRadius,p.startAngle,p.endAngle),e.arc(p.x,p.y,p.innerRadius,p.endAngle,p.startAngle,!0),e.closePath(),t=0;tt.x&&(e=jt(e,"left","right")):t.baseo?o:n,r:r.right||p<0?0:p>e?e:p,b:r.bottom||b<0?0:b>o?o:b,l:r.left||M<0?0:M>e?e:M}}function Ht(t){var e=Pt(t),o=e.right-e.left,n=e.bottom-e.top,p=Ft(t,o/2,n/2);return{outer:{x:e.left,y:e.top,w:o,h:n},inner:{x:e.left+p.l,y:e.top+p.t,w:o-p.l-p.r,h:n-p.t-p.b}}}function Ut(t,e,o){var n=null===e,p=null===o,b=!(!t||n&&p)&&Pt(t);return b&&(n||e>=b.left&&e<=b.right)&&(p||o>=b.top&&o<=b.bottom)}Q._set("global",{elements:{rectangle:{backgroundColor:Et,borderColor:Et,borderSkipped:"bottom",borderWidth:0}}});var Vt=dt.extend({_type:"rectangle",draw:function(){var t=this._chart.ctx,e=this._view,o=Ht(e),n=o.outer,p=o.inner;t.fillStyle=e.backgroundColor,t.fillRect(n.x,n.y,n.w,n.h),n.w===p.w&&n.h===p.h||(t.save(),t.beginPath(),t.rect(n.x,n.y,n.w,n.h),t.clip(),t.fillStyle=e.borderColor,t.rect(p.x,p.y,p.w,p.h),t.fill("evenodd"),t.restore())},height:function(){var t=this._view;return t.base-t.y},inRange:function(t,e){return Ut(this._view,t,e)},inLabelRange:function(t,e){var o=this._view;return Dt(o)?Ut(o,t,null):Ut(o,null,e)},inXRange:function(t){return Ut(this._view,t,null)},inYRange:function(t){return Ut(this._view,null,t)},getCenterPoint:function(){var t,e,o=this._view;return Dt(o)?(t=o.x,e=(o.y+o.base)/2):(t=(o.x+o.base)/2,e=o.y),{x:t,y:e}},getArea:function(){var t=this._view;return Dt(t)?t.width*Math.abs(t.y-t.base):t.height*Math.abs(t.x-t.base)},tooltipPosition:function(){var t=this._view;return{x:t.x,y:t.y}}}),$t={},Yt=Xt,Gt=wt,Jt=kt,Kt=Vt;$t.Arc=Yt,$t.Line=Gt,$t.Point=Jt,$t.Rectangle=Kt;var Qt=zt._deprecated,Zt=zt.valueOrDefault;function te(t,e){var o,n,p,b,M=t._length;for(p=1,b=e.length;p0?Math.min(M,Math.abs(n-o)):M,o=n;return M}function ee(t,e,o){var n,p,b=o.barThickness,M=e.stackCount,z=e.pixels[t],r=zt.isNullOrUndef(b)?te(e.scale,e.pixels):-1;return zt.isNullOrUndef(b)?(n=r*o.categoryPercentage,p=o.barPercentage):(n=b*M,p=1),{chunk:n/M,ratio:p,start:z-n/2}}function oe(t,e,o){var n,p=e.pixels,b=p[t],M=t>0?p[t-1]:null,z=t=0&&u.min>=0?u.min:u.max,W=void 0===u.start?u.end:u.max>=0&&u.min>=0?u.max-u.min:u.min-u.max,v=d.length;if(f||void 0===f&&void 0!==q)for(n=0;n=0&&c.max>=0?c.max:c.min,(u.min<0&&b<0||u.max>=0&&b>0)&&(h+=b));return M=O.getPixelForValue(h),r=(z=O.getPixelForValue(h+W))-M,void 0!==A&&Math.abs(r)=0&&!s||W<0&&s?M-A:M+A),{size:r,base:M,head:z,center:z+r/2}},calculateBarIndexPixels:function(t,e,o,n){var p=this,b="flex"===n.barThickness?oe(e,o,n):ee(e,o,n),M=p.getStackIndex(t,p.getMeta().stack),z=b.start+b.chunk*M+b.chunk/2,r=Math.min(Zt(n.maxBarThickness,1/0),b.chunk*b.ratio);return{base:z-r/2,head:z+r/2,center:z,size:r}},draw:function(){var t=this,e=t.chart,o=t._getValueScale(),n=t.getMeta().data,p=t.getDataset(),b=n.length,M=0;for(zt.canvas.clipArea(e.ctx,e.chartArea);M=re?-ce:f<-re?ce:0)+u,h=Math.cos(f),W=Math.sin(f),v=Math.cos(q),g=Math.sin(q),m=f<=0&&q>=0||q>=ce,R=f<=ie&&q>=ie||q>=ce+ie,y=f<=-ie&&q>=-ie||q>=re+ie,B=f===-re||q>=re?-1:Math.min(h,h*d,v,v*d),L=y?-1:Math.min(W,W*d,g,g*d),X=m?1:Math.max(h,h*d,v,v*d),_=R?1:Math.max(W,W*d,g,g*d);c=(X-B)/2,i=(_-L)/2,a=-(X+B)/2,O=-(_+L)/2}for(n=0,p=l.length;n0&&!isNaN(t)?ce*(Math.abs(t)/e):0},getMaxBorderWidth:function(t){var e,o,n,p,b,M,z,r,c=this,i=0,a=c.chart;if(!t)for(e=0,o=a.data.datasets.length;e(i=z>i?z:i)?r:i);return i},setHoverStyle:function(t){var e=t._model,o=t._options,n=zt.getHoverColor;t.$previousStyle={backgroundColor:e.backgroundColor,borderColor:e.borderColor,borderWidth:e.borderWidth},e.backgroundColor=ze(o.hoverBackgroundColor,n(o.backgroundColor)),e.borderColor=ze(o.hoverBorderColor,n(o.borderColor)),e.borderWidth=ze(o.hoverBorderWidth,o.borderWidth)},_getRingWeightOffset:function(t){for(var e=0,o=0;o0&&de(c[t-1]._model,r)&&(o.controlPointPreviousX=i(o.controlPointPreviousX,r.left,r.right),o.controlPointPreviousY=i(o.controlPointPreviousY,r.top,r.bottom)),t0&&(b=t.getDatasetMeta(b[0]._datasetIndex).data),b},"x-axis":function(t,e){return Ne(t,e,{intersect:!1})},point:function(t,e){return Le(t,ye(e,t))},nearest:function(t,e,o){var n=ye(e,t);o.axis=o.axis||"xy";var p=_e(o.axis);return Xe(t,n,o.intersect,p)},x:function(t,e,o){var n=ye(e,t),p=[],b=!1;return Be(t,(function(t){t.inXRange(n.x)&&p.push(t),t.inRange(n.x,n.y)&&(b=!0)})),o.intersect&&!b&&(p=[]),p},y:function(t,e,o){var n=ye(e,t),p=[],b=!1;return Be(t,(function(t){t.inYRange(n.y)&&p.push(t),t.inRange(n.x,n.y)&&(b=!0)})),o.intersect&&!b&&(p=[]),p}}},xe=zt.extend;function Te(t,e){return zt.where(t,(function(t){return t.pos===e}))}function Ce(t,e){return t.sort((function(t,o){var n=e?o:t,p=e?t:o;return n.weight===p.weight?n.index-p.index:n.weight-p.weight}))}function Se(t){var e,o,n,p=[];for(e=0,o=(t||[]).length;e div {\r\n\tposition: absolute;\r\n\twidth: 1000000px;\r\n\theight: 1000000px;\r\n\tleft: 0;\r\n\ttop: 0;\r\n}\r\n\r\n.chartjs-size-monitor-shrink > div {\r\n\tposition: absolute;\r\n\twidth: 200%;\r\n\theight: 200%;\r\n\tleft: 0;\r\n\ttop: 0;\r\n}\r\n",Ye=o(Object.freeze({__proto__:null,default:$e})),Ge="$chartjs",Je="chartjs-",Ke=Je+"size-monitor",Qe=Je+"render-monitor",Ze=Je+"render-animation",to=["animationstart","webkitAnimationStart"],eo={touchstart:"mousedown",touchmove:"mousemove",touchend:"mouseup",pointerenter:"mouseenter",pointerdown:"mousedown",pointermove:"mousemove",pointerup:"mouseup",pointerleave:"mouseout",pointerout:"mouseout"};function oo(t,e){var o=zt.getStyle(t,e),n=o&&o.match(/^(\d+)(\.\d+)?px$/);return n?Number(n[1]):void 0}function no(t,e){var o=t.style,n=t.getAttribute("height"),p=t.getAttribute("width");if(t[Ge]={initial:{height:n,width:p,style:{display:o.display,height:o.height,width:o.width}}},o.display=o.display||"block",null===p||""===p){var b=oo(t,"width");void 0!==b&&(t.width=b)}if(null===n||""===n)if(""===t.style.height)t.height=t.width/(e.options.aspectRatio||2);else{var M=oo(t,"height");void 0!==b&&(t.height=M)}return t}var po=function(){var t=!1;try{var e=Object.defineProperty({},"passive",{get:function(){t=!0}});window.addEventListener("e",null,e)}catch(t){}return t}(),bo=!!po&&{passive:!0};function Mo(t,e,o){t.addEventListener(e,o,bo)}function zo(t,e,o){t.removeEventListener(e,o,bo)}function ro(t,e,o,n,p){return{type:t,chart:e,native:p||null,x:void 0!==o?o:null,y:void 0!==n?n:null}}function co(t,e){var o=eo[t.type]||t.type,n=zt.getRelativePosition(t,e);return ro(o,e,n.x,n.y,t)}function io(t,e){var o=!1,n=[];return function(){n=Array.prototype.slice.call(arguments),e=e||this,o||(o=!0,zt.requestAnimFrame.call(window,(function(){o=!1,t.apply(e,n)})))}}function ao(t){var e=document.createElement("div");return e.className=t||"",e}function Oo(t){var e=1e6,o=ao(Ke),n=ao(Ke+"-expand"),p=ao(Ke+"-shrink");n.appendChild(ao()),p.appendChild(ao()),o.appendChild(n),o.appendChild(p),o._reset=function(){n.scrollLeft=e,n.scrollTop=e,p.scrollLeft=e,p.scrollTop=e};var b=function(){o._reset(),t()};return Mo(n,"scroll",b.bind(n,"expand")),Mo(p,"scroll",b.bind(p,"shrink")),o}function so(t,e){var o=t[Ge]||(t[Ge]={}),n=o.renderProxy=function(t){t.animationName===Ze&&e()};zt.each(to,(function(e){Mo(t,e,n)})),o.reflow=!!t.offsetParent,t.classList.add(Qe)}function lo(t){var e=t[Ge]||{},o=e.renderProxy;o&&(zt.each(to,(function(e){zo(t,e,o)})),delete e.renderProxy),t.classList.remove(Qe)}function uo(t,e,o){var n=t[Ge]||(t[Ge]={}),p=n.resizer=Oo(io((function(){if(n.resizer){var p=o.options.maintainAspectRatio&&t.parentNode,b=p?p.clientWidth:0;e(ro("resize",o)),p&&p.clientWidth0){var b=t[0];b.label?o=b.label:b.xLabel?o=b.xLabel:p>0&&b.index-1?t.split("\n"):t}function Xo(t){var e=t._xScale,o=t._yScale||t._scale,n=t._index,p=t._datasetIndex,b=t._chart.getDatasetMeta(p).controller,M=b._getIndexScale(),z=b._getValueScale();return{xLabel:e?e.getLabelForIndex(n,p):"",yLabel:o?o.getLabelForIndex(n,p):"",label:M?""+M.getLabelForIndex(n,p):"",value:z?""+z.getLabelForIndex(n,p):"",index:n,datasetIndex:p,x:t._model.x,y:t._model.y}}function _o(t){var e=Q.global;return{xPadding:t.xPadding,yPadding:t.yPadding,xAlign:t.xAlign,yAlign:t.yAlign,rtl:t.rtl,textDirection:t.textDirection,bodyFontColor:t.bodyFontColor,_bodyFontFamily:mo(t.bodyFontFamily,e.defaultFontFamily),_bodyFontStyle:mo(t.bodyFontStyle,e.defaultFontStyle),_bodyAlign:t.bodyAlign,bodyFontSize:mo(t.bodyFontSize,e.defaultFontSize),bodySpacing:t.bodySpacing,titleFontColor:t.titleFontColor,_titleFontFamily:mo(t.titleFontFamily,e.defaultFontFamily),_titleFontStyle:mo(t.titleFontStyle,e.defaultFontStyle),titleFontSize:mo(t.titleFontSize,e.defaultFontSize),_titleAlign:t.titleAlign,titleSpacing:t.titleSpacing,titleMarginBottom:t.titleMarginBottom,footerFontColor:t.footerFontColor,_footerFontFamily:mo(t.footerFontFamily,e.defaultFontFamily),_footerFontStyle:mo(t.footerFontStyle,e.defaultFontStyle),footerFontSize:mo(t.footerFontSize,e.defaultFontSize),_footerAlign:t.footerAlign,footerSpacing:t.footerSpacing,footerMarginTop:t.footerMarginTop,caretSize:t.caretSize,cornerRadius:t.cornerRadius,backgroundColor:t.backgroundColor,opacity:0,legendColorBackground:t.multiKeyBackground,displayColors:t.displayColors,borderColor:t.borderColor,borderWidth:t.borderWidth}}function No(t,e){var o=t._chart.ctx,n=2*e.yPadding,p=0,b=e.body,M=b.reduce((function(t,e){return t+e.before.length+e.lines.length+e.after.length}),0);M+=e.beforeBody.length+e.afterBody.length;var z=e.title.length,r=e.footer.length,c=e.titleFontSize,i=e.bodyFontSize,a=e.footerFontSize;n+=z*c,n+=z?(z-1)*e.titleSpacing:0,n+=z?e.titleMarginBottom:0,n+=M*i,n+=M?(M-1)*e.bodySpacing:0,n+=r?e.footerMarginTop:0,n+=r*a,n+=r?(r-1)*e.footerSpacing:0;var O=0,s=function(t){p=Math.max(p,o.measureText(t).width+O)};return o.font=zt.fontString(c,e._titleFontStyle,e._titleFontFamily),zt.each(e.title,s),o.font=zt.fontString(i,e._bodyFontStyle,e._bodyFontFamily),zt.each(e.beforeBody.concat(e.afterBody),s),O=e.displayColors?i+2:0,zt.each(b,(function(t){zt.each(t.before,s),zt.each(t.lines,s),zt.each(t.after,s)})),O=0,o.font=zt.fontString(a,e._footerFontStyle,e._footerFontFamily),zt.each(e.footer,s),{width:p+=2*e.xPadding,height:n}}function wo(t,e){var o,n,p,b,M,z=t._model,r=t._chart,c=t._chart.chartArea,i="center",a="center";z.yr.height-e.height&&(a="bottom");var O=(c.left+c.right)/2,s=(c.top+c.bottom)/2;"center"===a?(o=function(t){return t<=O},n=function(t){return t>O}):(o=function(t){return t<=e.width/2},n=function(t){return t>=r.width-e.width/2}),p=function(t){return t+e.width+z.caretSize+z.caretPadding>r.width},b=function(t){return t-e.width-z.caretSize-z.caretPadding<0},M=function(t){return t<=s?"top":"bottom"},o(z.x)?(i="left",p(z.x)&&(i="center",a=M(z.y))):n(z.x)&&(i="right",b(z.x)&&(i="center",a=M(z.y)));var l=t._options;return{xAlign:l.xAlign?l.xAlign:i,yAlign:l.yAlign?l.yAlign:a}}function xo(t,e,o,n){var p=t.x,b=t.y,M=t.caretSize,z=t.caretPadding,r=t.cornerRadius,c=o.xAlign,i=o.yAlign,a=M+z,O=r+z;return"right"===c?p-=e.width:"center"===c&&((p-=e.width/2)+e.width>n.width&&(p=n.width-e.width),p<0&&(p=0)),"top"===i?b+=a:b-="bottom"===i?e.height+a:e.height/2,"center"===i?"left"===c?p+=a:"right"===c&&(p-=a):"left"===c?p-=O:"right"===c&&(p+=O),{x:p,y:b}}function To(t,e){return"center"===e?t.x+t.width/2:"right"===e?t.x+t.width-t.xPadding:t.x+t.xPadding}function Co(t){return Bo([],Lo(t))}var So=dt.extend({initialize:function(){this._model=_o(this._options),this._lastActive=[]},getTitle:function(){var t=this,e=t._options.callbacks,o=e.beforeTitle.apply(t,arguments),n=e.title.apply(t,arguments),p=e.afterTitle.apply(t,arguments),b=[];return b=Bo(b,Lo(o)),b=Bo(b,Lo(n)),b=Bo(b,Lo(p))},getBeforeBody:function(){return Co(this._options.callbacks.beforeBody.apply(this,arguments))},getBody:function(t,e){var o=this,n=o._options.callbacks,p=[];return zt.each(t,(function(t){var b={before:[],lines:[],after:[]};Bo(b.before,Lo(n.beforeLabel.call(o,t,e))),Bo(b.lines,n.label.call(o,t,e)),Bo(b.after,Lo(n.afterLabel.call(o,t,e))),p.push(b)})),p},getAfterBody:function(){return Co(this._options.callbacks.afterBody.apply(this,arguments))},getFooter:function(){var t=this,e=t._options.callbacks,o=e.beforeFooter.apply(t,arguments),n=e.footer.apply(t,arguments),p=e.afterFooter.apply(t,arguments),b=[];return b=Bo(b,Lo(o)),b=Bo(b,Lo(n)),b=Bo(b,Lo(p))},update:function(t){var e,o,n=this,p=n._options,b=n._model,M=n._model=_o(p),z=n._active,r=n._data,c={xAlign:b.xAlign,yAlign:b.yAlign},i={x:b.x,y:b.y},a={width:b.width,height:b.height},O={x:b.caretX,y:b.caretY};if(z.length){M.opacity=1;var s=[],l=[];O=yo[p.position].call(n,z,n._eventPosition);var d=[];for(e=0,o=z.length;e0&&o.stroke()},draw:function(){var t=this._chart.ctx,e=this._view;if(0!==e.opacity){var o={width:e.width,height:e.height},n={x:e.x,y:e.y},p=Math.abs(e.opacity<.001)?0:e.opacity,b=e.title.length||e.beforeBody.length||e.body.length||e.afterBody.length||e.footer.length;this._options.enabled&&b&&(t.save(),t.globalAlpha=p,this.drawBackground(n,e,t,o),n.y+=e.yPadding,zt.rtl.overrideTextDirection(t,e.textDirection),this.drawTitle(n,e,t),this.drawBody(n,e,t),this.drawFooter(n,e,t),zt.rtl.restoreTextDirection(t,e.textDirection),t.restore())}},handleEvent:function(t){var e=this,o=e._options,n=!1;return e._lastActive=e._lastActive||[],"mouseout"===t.type?e._active=[]:(e._active=e._chart.getElementsAtEventForMode(t,o.mode,o),o.reverse&&e._active.reverse()),(n=!zt.arrayEquals(e._active,e._lastActive))&&(e._lastActive=e._active,(o.enabled||o.custom)&&(e._eventPosition={x:t.x,y:t.y},e.update(!0),e.pivot())),n}}),ko=yo,Eo=So;Eo.positioners=ko;var Do=zt.valueOrDefault;function Po(){return zt.merge(Object.create(null),[].slice.call(arguments),{merger:function(t,e,o,n){if("xAxes"===t||"yAxes"===t){var p,b,M,z=o[t].length;for(e[t]||(e[t]=[]),p=0;p=e[t].length&&e[t].push({}),!e[t][p].type||M.type&&M.type!==e[t][p].type?zt.merge(e[t][p],[go.getScaleDefaults(b),M]):zt.merge(e[t][p],M)}else zt._merger(t,e,o,n)}})}function jo(){return zt.merge(Object.create(null),[].slice.call(arguments),{merger:function(t,e,o,n){var p=e[t]||Object.create(null),b=o[t];"scales"===t?e[t]=Po(p,b):"scale"===t?e[t]=zt.merge(p,[go.getScaleDefaults(b.type),b]):zt._merger(t,e,o,n)}})}function Io(t){var e=(t=t||Object.create(null)).data=t.data||{};return e.datasets=e.datasets||[],e.labels=e.labels||[],t.options=jo(Q.global,Q[t.type],t.options||{}),t}function Fo(t){var e=t.options;zt.each(t.scales,(function(e){Ue.removeBox(t,e)})),e=jo(Q.global,Q[t.config.type],e),t.options=t.config.options=e,t.ensureScalesHaveIDs(),t.buildOrUpdateScales(),t.tooltip._options=e.tooltips,t.tooltip.initialize()}function Ho(t,e,o){var n,p=function(t){return t.id===n};do{n=e+o++}while(zt.findIndex(t,p)>=0);return n}function Uo(t){return"top"===t||"bottom"===t}function Vo(t,e){return function(o,n){return o[t]===n[t]?o[e]-n[e]:o[t]-n[t]}}Q._set("global",{elements:{},events:["mousemove","mouseout","click","touchstart","touchmove"],hover:{onHover:null,mode:"nearest",intersect:!0,animationDuration:400},onClick:null,maintainAspectRatio:!0,responsive:!0,responsiveAnimationDuration:0});var $o=function(t,e){return this.construct(t,e),this};zt.extend($o.prototype,{construct:function(t,e){var o=this;e=Io(e);var n=Wo.acquireContext(t,e),p=n&&n.canvas,b=p&&p.height,M=p&&p.width;o.id=zt.uid(),o.ctx=n,o.canvas=p,o.config=e,o.width=M,o.height=b,o.aspectRatio=b?M/b:null,o.options=e.options,o._bufferedRender=!1,o._layers=[],o.chart=o,o.controller=o,$o.instances[o.id]=o,Object.defineProperty(o,"data",{get:function(){return o.config.data},set:function(t){o.config.data=t}}),n&&p&&(o.initialize(),o.update())},initialize:function(){var t=this;return vo.notify(t,"beforeInit"),zt.retinaScale(t,t.options.devicePixelRatio),t.bindEvents(),t.options.responsive&&t.resize(!0),t.initToolTip(),vo.notify(t,"afterInit"),t},clear:function(){return zt.canvas.clear(this),this},stop:function(){return ft.cancelAnimation(this),this},resize:function(t){var e=this,o=e.options,n=e.canvas,p=o.maintainAspectRatio&&e.aspectRatio||null,b=Math.max(0,Math.floor(zt.getMaximumWidth(n))),M=Math.max(0,Math.floor(p?b/p:zt.getMaximumHeight(n)));if((e.width!==b||e.height!==M)&&(n.width=e.width=b,n.height=e.height=M,n.style.width=b+"px",n.style.height=M+"px",zt.retinaScale(e,o.devicePixelRatio),!t)){var z={width:b,height:M};vo.notify(e,"resize",[z]),o.onResize&&o.onResize(e,z),e.stop(),e.update({duration:o.responsiveAnimationDuration})}},ensureScalesHaveIDs:function(){var t=this.options,e=t.scales||{},o=t.scale;zt.each(e.xAxes,(function(t,o){t.id||(t.id=Ho(e.xAxes,"x-axis-",o))})),zt.each(e.yAxes,(function(t,o){t.id||(t.id=Ho(e.yAxes,"y-axis-",o))})),o&&(o.id=o.id||"scale")},buildOrUpdateScales:function(){var t=this,e=t.options,o=t.scales||{},n=[],p=Object.keys(o).reduce((function(t,e){return t[e]=!1,t}),{});e.scales&&(n=n.concat((e.scales.xAxes||[]).map((function(t){return{options:t,dtype:"category",dposition:"bottom"}})),(e.scales.yAxes||[]).map((function(t){return{options:t,dtype:"linear",dposition:"left"}})))),e.scale&&n.push({options:e.scale,dtype:"radialLinear",isDefault:!0,dposition:"chartArea"}),zt.each(n,(function(e){var n=e.options,b=n.id,M=Do(n.type,e.dtype);Uo(n.position)!==Uo(e.dposition)&&(n.position=e.dposition),p[b]=!0;var z=null;if(b in o&&o[b].type===M)(z=o[b]).options=n,z.ctx=t.ctx,z.chart=t;else{var r=go.getScaleConstructor(M);if(!r)return;z=new r({id:b,type:M,options:n,ctx:t.ctx,chart:t}),o[z.id]=z}z.mergeTicksOptions(),e.isDefault&&(t.scale=z)})),zt.each(p,(function(t,e){t||delete o[e]})),t.scales=o,go.addScalesToLayout(this)},buildOrUpdateControllers:function(){var t,e,o=this,n=[],p=o.data.datasets;for(t=0,e=p.length;t=0;--o)n.drawDataset(e[o],t);vo.notify(n,"afterDatasetsDraw",[t])}},drawDataset:function(t,e){var o=this,n={meta:t,index:t.index,easingValue:e};!1!==vo.notify(o,"beforeDatasetDraw",[n])&&(t.controller.draw(e),vo.notify(o,"afterDatasetDraw",[n]))},_drawTooltip:function(t){var e=this,o=e.tooltip,n={tooltip:o,easingValue:t};!1!==vo.notify(e,"beforeTooltipDraw",[n])&&(o.draw(),vo.notify(e,"afterTooltipDraw",[n]))},getElementAtEvent:function(t){return we.modes.single(this,t)},getElementsAtEvent:function(t){return we.modes.label(this,t,{intersect:!0})},getElementsAtXAxis:function(t){return we.modes["x-axis"](this,t,{intersect:!0})},getElementsAtEventForMode:function(t,e,o){var n=we.modes[e];return"function"==typeof n?n(this,t,o):[]},getDatasetAtEvent:function(t){return we.modes.dataset(this,t,{intersect:!0})},getDatasetMeta:function(t){var e=this,o=e.data.datasets[t];o._meta||(o._meta={});var n=o._meta[e.id];return n||(n=o._meta[e.id]={type:null,data:[],dataset:null,controller:null,hidden:null,xAxisID:null,yAxisID:null,order:o.order||0,index:t}),n},getVisibleDatasetCount:function(){for(var t=0,e=0,o=this.data.datasets.length;e=0;n--){var p=t[n];if(e(p))return p}},zt.isNumber=function(t){return!isNaN(parseFloat(t))&&isFinite(t)},zt.almostEquals=function(t,e,o){return Math.abs(t-e)=t},zt.max=function(t){return t.reduce((function(t,e){return isNaN(e)?t:Math.max(t,e)}),Number.NEGATIVE_INFINITY)},zt.min=function(t){return t.reduce((function(t,e){return isNaN(e)?t:Math.min(t,e)}),Number.POSITIVE_INFINITY)},zt.sign=Math.sign?function(t){return Math.sign(t)}:function(t){return 0==(t=+t)||isNaN(t)?t:t>0?1:-1},zt.toRadians=function(t){return t*(Math.PI/180)},zt.toDegrees=function(t){return t*(180/Math.PI)},zt._decimalPlaces=function(t){if(zt.isFinite(t)){for(var e=1,o=0;Math.round(t*e)/e!==t;)e*=10,o++;return o}},zt.getAngleFromPoint=function(t,e){var o=e.x-t.x,n=e.y-t.y,p=Math.sqrt(o*o+n*n),b=Math.atan2(n,o);return b<-.5*Math.PI&&(b+=2*Math.PI),{angle:b,distance:p}},zt.distanceBetweenPoints=function(t,e){return Math.sqrt(Math.pow(e.x-t.x,2)+Math.pow(e.y-t.y,2))},zt.aliasPixel=function(t){return t%2==0?0:.5},zt._alignPixel=function(t,e,o){var n=t.currentDevicePixelRatio,p=o/2;return Math.round((e-p)*n)/n+p},zt.splineCurve=function(t,e,o,n){var p=t.skip?e:t,b=e,M=o.skip?e:o,z=Math.sqrt(Math.pow(b.x-p.x,2)+Math.pow(b.y-p.y,2)),r=Math.sqrt(Math.pow(M.x-b.x,2)+Math.pow(M.y-b.y,2)),c=z/(z+r),i=r/(z+r),a=n*(c=isNaN(c)?0:c),O=n*(i=isNaN(i)?0:i);return{previous:{x:b.x-a*(M.x-p.x),y:b.y-a*(M.y-p.y)},next:{x:b.x+O*(M.x-p.x),y:b.y+O*(M.y-p.y)}}},zt.EPSILON=Number.EPSILON||1e-14,zt.splineCurveMonotone=function(t){var e,o,n,p,b,M,z,r,c,i=(t||[]).map((function(t){return{model:t._model,deltaK:0,mK:0}})),a=i.length;for(e=0;e0?i[e-1]:null,(p=e0?i[e-1]:null,p=e=t.length-1?t[0]:t[e+1]:e>=t.length-1?t[t.length-1]:t[e+1]},zt.previousItem=function(t,e,o){return o?e<=0?t[t.length-1]:t[e-1]:e<=0?t[0]:t[e-1]},zt.niceNum=function(t,e){var o=Math.floor(zt.log10(t)),n=t/Math.pow(10,o);return(e?n<1.5?1:n<3?2:n<7?5:10:n<=1?1:n<=2?2:n<=5?5:10)*Math.pow(10,o)},zt.requestAnimFrame="undefined"==typeof window?function(t){t()}:window.requestAnimationFrame||window.webkitRequestAnimationFrame||window.mozRequestAnimationFrame||window.oRequestAnimationFrame||window.msRequestAnimationFrame||function(t){return window.setTimeout(t,1e3/60)},zt.getRelativePosition=function(t,e){var o,n,p=t.originalEvent||t,b=t.target||t.srcElement,M=b.getBoundingClientRect(),z=p.touches;z&&z.length>0?(o=z[0].clientX,n=z[0].clientY):(o=p.clientX,n=p.clientY);var r=parseFloat(zt.getStyle(b,"padding-left")),c=parseFloat(zt.getStyle(b,"padding-top")),i=parseFloat(zt.getStyle(b,"padding-right")),a=parseFloat(zt.getStyle(b,"padding-bottom")),O=M.right-M.left-r-i,s=M.bottom-M.top-c-a;return{x:o=Math.round((o-M.left-r)/O*b.width/e.currentDevicePixelRatio),y:n=Math.round((n-M.top-c)/s*b.height/e.currentDevicePixelRatio)}},zt.getConstraintWidth=function(t){return o(t,"max-width","clientWidth")},zt.getConstraintHeight=function(t){return o(t,"max-height","clientHeight")},zt._calculatePadding=function(t,e,o){return(e=zt.getStyle(t,e)).indexOf("%")>-1?o*parseInt(e,10)/100:parseInt(e,10)},zt._getParentNode=function(t){var e=t.parentNode;return e&&"[object ShadowRoot]"===e.toString()&&(e=e.host),e},zt.getMaximumWidth=function(t){var e=zt._getParentNode(t);if(!e)return t.clientWidth;var o=e.clientWidth,n=o-zt._calculatePadding(e,"padding-left",o)-zt._calculatePadding(e,"padding-right",o),p=zt.getConstraintWidth(t);return isNaN(p)?n:Math.min(n,p)},zt.getMaximumHeight=function(t){var e=zt._getParentNode(t);if(!e)return t.clientHeight;var o=e.clientHeight,n=o-zt._calculatePadding(e,"padding-top",o)-zt._calculatePadding(e,"padding-bottom",o),p=zt.getConstraintHeight(t);return isNaN(p)?n:Math.min(n,p)},zt.getStyle=function(t,e){return t.currentStyle?t.currentStyle[e]:document.defaultView.getComputedStyle(t,null).getPropertyValue(e)},zt.retinaScale=function(t,e){var o=t.currentDevicePixelRatio=e||"undefined"!=typeof window&&window.devicePixelRatio||1;if(1!==o){var n=t.canvas,p=t.height,b=t.width;n.height=p*o,n.width=b*o,t.ctx.scale(o,o),n.style.height||n.style.width||(n.style.height=p+"px",n.style.width=b+"px")}},zt.fontString=function(t,e,o){return e+" "+t+"px "+o},zt.longestText=function(t,e,o,n){var p=(n=n||{}).data=n.data||{},b=n.garbageCollect=n.garbageCollect||[];n.font!==e&&(p=n.data={},b=n.garbageCollect=[],n.font=e),t.font=e;var M,z,r,c,i,a=0,O=o.length;for(M=0;Mo.length){for(M=0;Mn&&(n=b),n},zt.numberOfLabelLines=function(t){var e=1;return zt.each(t,(function(t){zt.isArray(t)&&t.length>e&&(e=t.length)})),e},zt.color=S?function(t){return t instanceof CanvasGradient&&(t=Q.global.defaultColor),S(t)}:function(t){return t},zt.getHoverColor=function(t){return t instanceof CanvasPattern||t instanceof CanvasGradient?t:zt.color(t).saturate(.5).darken(.1).rgbString()}};function Jo(){throw new Error("This method is not implemented: either no adapter can be found or an incomplete integration was provided.")}function Ko(t){this.options=t||{}}zt.extend(Ko.prototype,{formats:Jo,parse:Jo,format:Jo,add:Jo,diff:Jo,startOf:Jo,endOf:Jo,_create:function(t){return t}}),Ko.override=function(t){zt.extend(Ko.prototype,t)};var Qo={_date:Ko},Zo={formatters:{values:function(t){return zt.isArray(t)?t:""+t},linear:function(t,e,o){var n=o.length>3?o[2]-o[1]:o[1]-o[0];Math.abs(n)>1&&t!==Math.floor(t)&&(n=t-Math.floor(t));var p=zt.log10(Math.abs(n)),b="";if(0!==t)if(Math.max(Math.abs(o[0]),Math.abs(o[o.length-1]))<1e-4){var M=zt.log10(Math.abs(t)),z=Math.floor(M)-Math.floor(p);z=Math.max(Math.min(z,20),0),b=t.toExponential(z)}else{var r=-1*Math.floor(p);r=Math.max(Math.min(r,20),0),b=t.toFixed(r)}else b="0";return b},logarithmic:function(t,e,o){var n=t/Math.pow(10,Math.floor(zt.log10(t)));return 0===t?"0":1===n||2===n||5===n||0===e||e===o.length-1?t.toExponential():""}}},tn=zt.isArray,en=zt.isNullOrUndef,on=zt.valueOrDefault,nn=zt.valueAtIndexOrDefault;function pn(t,e){for(var o=[],n=t.length/e,p=0,b=t.length;pr+c)))return M}function Mn(t,e){zt.each(t,(function(t){var o,n=t.gc,p=n.length/2;if(p>e){for(o=0;oc)return b;return Math.max(c,1)}function un(t){var e,o,n=[];for(e=0,o=t.length;e=O||i<=1||!z.isHorizontal()?z.labelRotation=a:(e=(t=z._getLabelSizes()).widest.width,o=t.highest.height-t.highest.offset,n=Math.min(z.maxWidth,z.chart.width-e),e+6>(p=r.offset?z.maxWidth/i:n/(i-1))&&(p=n/(i-(r.offset?.5:1)),b=z.maxHeight-rn(r.gridLines)-c.padding-cn(r.scaleLabel),M=Math.sqrt(e*e+o*o),s=zt.toDegrees(Math.min(Math.asin(Math.min((t.highest.height+6)/p,1)),Math.asin(Math.min(b/M,1))-Math.asin(o/M))),s=Math.max(a,Math.min(O,s))),z.labelRotation=s)},afterCalculateTickRotation:function(){zt.callback(this.options.afterCalculateTickRotation,[this])},beforeFit:function(){zt.callback(this.options.beforeFit,[this])},fit:function(){var t=this,e=t.minSize={width:0,height:0},o=t.chart,n=t.options,p=n.ticks,b=n.scaleLabel,M=n.gridLines,z=t._isVisible(),r="bottom"===n.position,c=t.isHorizontal();if(c?e.width=t.maxWidth:z&&(e.width=rn(M)+cn(b)),c?z&&(e.height=rn(M)+cn(b)):e.height=t.maxHeight,p.display&&z){var i=On(p),a=t._getLabelSizes(),O=a.first,s=a.last,l=a.widest,d=a.highest,u=.4*i.minor.lineHeight,A=p.padding;if(c){var f=0!==t.labelRotation,q=zt.toRadians(t.labelRotation),h=Math.cos(q),W=Math.sin(q),v=W*l.width+h*(d.height-(f?d.offset:0))+(f?0:u);e.height=Math.min(t.maxHeight,e.height+v+A);var g,m,R=t.getPixelForTick(0)-t.left,y=t.right-t.getPixelForTick(t.getTicks().length-1);f?(g=r?h*O.width+W*O.offset:W*(O.height-O.offset),m=r?W*(s.height-s.offset):h*s.width+W*s.offset):(g=O.width/2,m=s.width/2),t.paddingLeft=Math.max((g-R)*t.width/(t.width-R),0)+3,t.paddingRight=Math.max((m-y)*t.width/(t.width-y),0)+3}else{var B=p.mirror?0:l.width+A+u;e.width=Math.min(t.maxWidth,e.width+B),t.paddingTop=O.height/2,t.paddingBottom=s.height/2}}t.handleMargins(),c?(t.width=t._length=o.width-t.margins.left-t.margins.right,t.height=e.height):(t.width=e.width,t.height=t._length=o.height-t.margins.top-t.margins.bottom)},handleMargins:function(){var t=this;t.margins&&(t.margins.left=Math.max(t.paddingLeft,t.margins.left),t.margins.top=Math.max(t.paddingTop,t.margins.top),t.margins.right=Math.max(t.paddingRight,t.margins.right),t.margins.bottom=Math.max(t.paddingBottom,t.margins.bottom))},afterFit:function(){zt.callback(this.options.afterFit,[this])},isHorizontal:function(){var t=this.options.position;return"top"===t||"bottom"===t},isFullWidth:function(){return this.options.fullWidth},getRightValue:function(t){if(en(t))return NaN;if(("number"==typeof t||t instanceof Number)&&!isFinite(t))return NaN;if(t)if(this.isHorizontal()){if(void 0!==t.x)return this.getRightValue(t.x)}else if(void 0!==t.y)return this.getRightValue(t.y);return t},_convertTicksToLabels:function(t){var e,o,n,p=this;for(p.ticks=t.map((function(t){return t.value})),p.beforeTickToLabelConversion(),e=p.convertTicksToLabels(t)||p.ticks,p.afterTickToLabelConversion(),o=0,n=t.length;on-1?null:e.getPixelForDecimal(t*p+(o?p/2:0))},getPixelForDecimal:function(t){var e=this;return e._reversePixels&&(t=1-t),e._startPixel+t*e._length},getDecimalForPixel:function(t){var e=(t-this._startPixel)/this._length;return this._reversePixels?1-e:e},getBasePixel:function(){return this.getPixelForValue(this.getBaseValue())},getBaseValue:function(){var t=this,e=t.min,o=t.max;return t.beginAtZero?0:e<0&&o<0?o:e>0&&o>0?e:0},_autoSkip:function(t){var e,o,n,p,b=this,M=b.options.ticks,z=b._length,r=M.maxTicksLimit||z/b._tickSize()+1,c=M.major.enabled?un(t):[],i=c.length,a=c[0],O=c[i-1];if(i>r)return An(t,c,i/r),sn(t);if(n=dn(c,t,z,r),i>0){for(e=0,o=i-1;e1?(O-a)/(i-1):null,fn(t,n,zt.isNullOrUndef(p)?0:a-p,a),fn(t,n,O,zt.isNullOrUndef(p)?t.length:O+p),sn(t)}return fn(t,n),sn(t)},_tickSize:function(){var t=this,e=t.options.ticks,o=zt.toRadians(t.labelRotation),n=Math.abs(Math.cos(o)),p=Math.abs(Math.sin(o)),b=t._getLabelSizes(),M=e.autoSkipPadding||0,z=b?b.widest.width+M:0,r=b?b.highest.height+M:0;return t.isHorizontal()?r*n>z*p?z/n:r/p:r*p=0&&(M=t),void 0!==b&&(t=o.indexOf(b))>=0&&(z=t),e.minIndex=M,e.maxIndex=z,e.min=o[M],e.max=o[z]},buildTicks:function(){var t=this,e=t._getLabels(),o=t.minIndex,n=t.maxIndex;t.ticks=0===o&&n===e.length-1?e:e.slice(o,n+1)},getLabelForIndex:function(t,e){var o=this,n=o.chart;return n.getDatasetMeta(e).controller._getValueScaleId()===o.id?o.getRightValue(n.data.datasets[e].data[t]):o._getLabels()[t]},_configure:function(){var t=this,e=t.options.offset,o=t.ticks;hn.prototype._configure.call(t),t.isHorizontal()||(t._reversePixels=!t._reversePixels),o&&(t._startValue=t.minIndex-(e?.5:0),t._valueRange=Math.max(o.length-(e?0:1),1))},getPixelForValue:function(t,e,o){var n,p,b,M=this;return Wn(e)||Wn(o)||(t=M.chart.data.datasets[o].data[e]),Wn(t)||(n=M.isHorizontal()?t.x:t.y),(void 0!==n||void 0!==t&&isNaN(e))&&(p=M._getLabels(),t=zt.valueOrDefault(n,t),e=-1!==(b=p.indexOf(t))?b:e,isNaN(e)&&(e=t)),M.getPixelForDecimal((e-M._startValue)/M._valueRange)},getPixelForTick:function(t){var e=this.ticks;return t<0||t>e.length-1?null:this.getPixelForValue(e[t],t+this.minIndex)},getValueForPixel:function(t){var e=this,o=Math.round(e._startValue+e.getDecimalForPixel(t)*e._valueRange);return Math.min(Math.max(o,0),e.ticks.length-1)},getBasePixel:function(){return this.bottom}}),mn=vn;gn._defaults=mn;var Rn=zt.noop,yn=zt.isNullOrUndef;function Bn(t,e){var o,n,p,b,M=[],z=1e-14,r=t.stepSize,c=r||1,i=t.maxTicks-1,a=t.min,O=t.max,s=t.precision,l=e.min,d=e.max,u=zt.niceNum((d-l)/i/c)*c;if(ui&&(u=zt.niceNum(b*u/i/c)*c),r||yn(s)?o=Math.pow(10,zt._decimalPlaces(u)):(o=Math.pow(10,s),u=Math.ceil(u*o)/o),n=Math.floor(l/u)*u,p=Math.ceil(d/u)*u,r&&(!yn(a)&&zt.almostWhole(a/u,u/1e3)&&(n=a),!yn(O)&&zt.almostWhole(O/u,u/1e3)&&(p=O)),b=(p-n)/u,b=zt.almostEquals(b,Math.round(b),u/1e3)?Math.round(b):Math.ceil(b),n=Math.round(n*o)/o,p=Math.round(p*o)/o,M.push(yn(a)?n:a);for(var A=1;A0&&n>0&&(t.min=0)}var p=void 0!==e.min||void 0!==e.suggestedMin,b=void 0!==e.max||void 0!==e.suggestedMax;void 0!==e.min?t.min=e.min:void 0!==e.suggestedMin&&(null===t.min?t.min=e.suggestedMin:t.min=Math.min(t.min,e.suggestedMin)),void 0!==e.max?t.max=e.max:void 0!==e.suggestedMax&&(null===t.max?t.max=e.suggestedMax:t.max=Math.max(t.max,e.suggestedMax)),p!==b&&t.min>=t.max&&(p?t.max=t.min+1:t.min=t.max-1),t.min===t.max&&(t.max++,e.beginAtZero||t.min--)},getTickLimit:function(){var t,e=this,o=e.options.ticks,n=o.stepSize,p=o.maxTicksLimit;return n?t=Math.ceil(e.max/n)-Math.floor(e.min/n)+1:(t=e._computeTickLimit(),p=p||11),p&&(t=Math.min(p,t)),t},_computeTickLimit:function(){return Number.POSITIVE_INFINITY},handleDirectionalChanges:Rn,buildTicks:function(){var t=this,e=t.options.ticks,o=t.getTickLimit(),n={maxTicks:o=Math.max(2,o),min:e.min,max:e.max,precision:e.precision,stepSize:zt.valueOrDefault(e.fixedStepSize,e.stepSize)},p=t.ticks=Bn(n,t);t.handleDirectionalChanges(),t.max=zt.max(p),t.min=zt.min(p),e.reverse?(p.reverse(),t.start=t.max,t.end=t.min):(t.start=t.min,t.end=t.max)},convertTicksToLabels:function(){var t=this;t.ticksAsNumbers=t.ticks.slice(),t.zeroLineIndex=t.ticks.indexOf(0),hn.prototype.convertTicksToLabels.call(t)},_configure:function(){var t,e=this,o=e.getTicks(),n=e.min,p=e.max;hn.prototype._configure.call(e),e.options.offset&&o.length&&(n-=t=(p-n)/Math.max(o.length-1,1)/2,p+=t),e._startValue=n,e._endValue=p,e._valueRange=p-n}}),Xn={position:"left",ticks:{callback:Zo.formatters.linear}},_n=0,Nn=1;function wn(t,e,o){var n=[o.type,void 0===e&&void 0===o.stack?o.index:"",o.stack].join(".");return void 0===t[n]&&(t[n]={pos:[],neg:[]}),t[n]}function xn(t,e,o,n){var p,b,M=t.options,z=wn(e,M.stacked,o),r=z.pos,c=z.neg,i=n.length;for(p=0;pe.length-1?null:this.getPixelForValue(e[t])}}),Sn=Xn;Cn._defaults=Sn;var kn=zt.valueOrDefault,En=zt.math.log10;function Dn(t,e){var o,n,p=[],b=kn(t.min,Math.pow(10,Math.floor(En(e.min)))),M=Math.floor(En(e.max)),z=Math.ceil(e.max/Math.pow(10,M));0===b?(o=Math.floor(En(e.minNotZero)),n=Math.floor(e.minNotZero/Math.pow(10,o)),p.push(b),b=n*Math.pow(10,o)):(o=Math.floor(En(b)),n=Math.floor(b/Math.pow(10,o)));var r=o<0?Math.pow(10,Math.abs(o)):1;do{p.push(b),10==++n&&(n=1,r=++o>=0?1:r),b=Math.round(n*Math.pow(10,o)*r)/r}while(o=0?t:e}var In=hn.extend({determineDataLimits:function(){var t,e,o,n,p,b,M=this,z=M.options,r=M.chart,c=r.data.datasets,i=M.isHorizontal();function a(t){return i?t.xAxisID===M.id:t.yAxisID===M.id}M.min=Number.POSITIVE_INFINITY,M.max=Number.NEGATIVE_INFINITY,M.minNotZero=Number.POSITIVE_INFINITY;var O=z.stacked;if(void 0===O)for(t=0;t0){var e=zt.min(t),o=zt.max(t);M.min=Math.min(M.min,e),M.max=Math.max(M.max,o)}}))}else for(t=0;t0?t.minNotZero=t.min:t.max<1?t.minNotZero=Math.pow(10,Math.floor(En(t.max))):t.minNotZero=o)},buildTicks:function(){var t=this,e=t.options.ticks,o=!t.isHorizontal(),n={min:jn(e.min),max:jn(e.max)},p=t.ticks=Dn(n,t);t.max=zt.max(p),t.min=zt.min(p),e.reverse?(o=!o,t.start=t.max,t.end=t.min):(t.start=t.min,t.end=t.max),o&&p.reverse()},convertTicksToLabels:function(){this.tickValues=this.ticks.slice(),hn.prototype.convertTicksToLabels.call(this)},getLabelForIndex:function(t,e){return this._getScaleLabel(this.chart.data.datasets[e].data[t])},getPixelForTick:function(t){var e=this.tickValues;return t<0||t>e.length-1?null:this.getPixelForValue(e[t])},_getFirstTickValue:function(t){var e=Math.floor(En(t));return Math.floor(t/Math.pow(10,e))*Math.pow(10,e)},_configure:function(){var t=this,e=t.min,o=0;hn.prototype._configure.call(t),0===e&&(e=t._getFirstTickValue(t.minNotZero),o=kn(t.options.ticks.fontSize,Q.global.defaultFontSize)/t._length),t._startValue=En(e),t._valueOffset=o,t._valueRange=(En(t.max)-En(e))/(1-o)},getPixelForValue:function(t){var e=this,o=0;return(t=+e.getRightValue(t))>e.min&&t>0&&(o=(En(t)-e._startValue)/e._valueRange+e._valueOffset),e.getPixelForDecimal(o)},getValueForPixel:function(t){var e=this,o=e.getDecimalForPixel(t);return 0===o&&0===e.min?0:Math.pow(10,e._startValue+(o-e._valueOffset)*e._valueRange)}}),Fn=Pn;In._defaults=Fn;var Hn=zt.valueOrDefault,Un=zt.valueAtIndexOrDefault,Vn=zt.options.resolve,$n={display:!0,animate:!0,position:"chartArea",angleLines:{display:!0,color:"rgba(0,0,0,0.1)",lineWidth:1,borderDash:[],borderDashOffset:0},gridLines:{circular:!1},ticks:{showLabelBackdrop:!0,backdropColor:"rgba(255,255,255,0.75)",backdropPaddingY:2,backdropPaddingX:2,callback:Zo.formatters.linear},pointLabels:{display:!0,fontSize:10,callback:function(t){return t}}};function Yn(t){var e=t.ticks;return e.display&&t.display?Hn(e.fontSize,Q.global.defaultFontSize)+2*e.backdropPaddingY:0}function Gn(t,e,o){return zt.isArray(o)?{w:zt.longestText(t,t.font,o),h:o.length*e}:{w:t.measureText(o).width,h:e}}function Jn(t,e,o,n,p){return t===n||t===p?{start:e-o/2,end:e+o/2}:tp?{start:e-o,end:e}:{start:e,end:e+o}}function Kn(t){var e,o,n,p=zt.options._parseFont(t.options.pointLabels),b={l:0,r:t.width,t:0,b:t.height-t.paddingTop},M={};t.ctx.font=p.string,t._pointLabelSizes=[];var z=t.chart.data.labels.length;for(e=0;eb.r&&(b.r=i.end,M.r=r),a.startb.b&&(b.b=a.end,M.b=r)}t.setReductions(t.drawingArea,b,M)}function Qn(t){return 0===t||180===t?"center":t<180?"left":"right"}function Zn(t,e,o,n){var p,b,M=o.y+n/2;if(zt.isArray(e))for(p=0,b=e.length;p270||t<90)&&(o.y-=e.h)}function ep(t){var e=t.ctx,o=t.options,n=o.pointLabels,p=Yn(o),b=t.getDistanceFromCenterForValue(o.ticks.reverse?t.min:t.max),M=zt.options._parseFont(n);e.save(),e.font=M.string,e.textBaseline="middle";for(var z=t.chart.data.labels.length-1;z>=0;z--){var r=0===z?p/2:0,c=t.getPointPosition(z,b+r+5),i=Un(n.fontColor,z,Q.global.defaultFontColor);e.fillStyle=i;var a=t.getIndexAngle(z),O=zt.toDegrees(a);e.textAlign=Qn(O),tp(O,t._pointLabelSizes[z],c),Zn(e,t.pointLabels[z],c,M.lineHeight)}e.restore()}function op(t,e,o,n){var p,b=t.ctx,M=e.circular,z=t.chart.data.labels.length,r=Un(e.color,n-1),c=Un(e.lineWidth,n-1);if((M||z)&&r&&c){if(b.save(),b.strokeStyle=r,b.lineWidth=c,b.setLineDash&&(b.setLineDash(e.borderDash||[]),b.lineDashOffset=e.borderDashOffset||0),b.beginPath(),M)b.arc(t.xCenter,t.yCenter,o,0,2*Math.PI);else{p=t.getPointPosition(0,o),b.moveTo(p.x,p.y);for(var i=1;i0&&n>0?o:0)},_drawGrid:function(){var t,e,o,n=this,p=n.ctx,b=n.options,M=b.gridLines,z=b.angleLines,r=Hn(z.lineWidth,M.lineWidth),c=Hn(z.color,M.color);if(b.pointLabels.display&&ep(n),M.display&&zt.each(n.ticks,(function(t,o){0!==o&&(e=n.getDistanceFromCenterForValue(n.ticksAsNumbers[o]),op(n,M,e,o))})),z.display&&r&&c){for(p.save(),p.lineWidth=r,p.strokeStyle=c,p.setLineDash&&(p.setLineDash(Vn([z.borderDash,M.borderDash,[]])),p.lineDashOffset=Vn([z.borderDashOffset,M.borderDashOffset,0])),t=n.chart.data.labels.length-1;t>=0;t--)e=n.getDistanceFromCenterForValue(b.ticks.reverse?n.min:n.max),o=n.getPointPosition(t,e),p.beginPath(),p.moveTo(n.xCenter,n.yCenter),p.lineTo(o.x,o.y),p.stroke();p.restore()}},_drawLabels:function(){var t=this,e=t.ctx,o=t.options.ticks;if(o.display){var n,p,b=t.getIndexAngle(0),M=zt.options._parseFont(o),z=Hn(o.fontColor,Q.global.defaultFontColor);e.save(),e.font=M.string,e.translate(t.xCenter,t.yCenter),e.rotate(b),e.textAlign="center",e.textBaseline="middle",zt.each(t.ticks,(function(b,r){(0!==r||o.reverse)&&(n=t.getDistanceFromCenterForValue(t.ticksAsNumbers[r]),o.showLabelBackdrop&&(p=e.measureText(b).width,e.fillStyle=o.backdropColor,e.fillRect(-p/2-o.backdropPaddingX,-n-M.size/2-o.backdropPaddingY,p+2*o.backdropPaddingX,M.size+2*o.backdropPaddingY)),e.fillStyle=z,e.fillText(b,0,-n))})),e.restore()}},_drawTitle:zt.noop}),bp=$n;pp._defaults=bp;var Mp=zt._deprecated,zp=zt.options.resolve,rp=zt.valueOrDefault,cp=Number.MIN_SAFE_INTEGER||-9007199254740991,ip=Number.MAX_SAFE_INTEGER||9007199254740991,ap={millisecond:{common:!0,size:1,steps:1e3},second:{common:!0,size:1e3,steps:60},minute:{common:!0,size:6e4,steps:60},hour:{common:!0,size:36e5,steps:24},day:{common:!0,size:864e5,steps:30},week:{common:!1,size:6048e5,steps:4},month:{common:!0,size:2628e6,steps:12},quarter:{common:!1,size:7884e6,steps:4},year:{common:!0,size:3154e7}},Op=Object.keys(ap);function sp(t,e){return t-e}function lp(t){var e,o,n,p={},b=[];for(e=0,o=t.length;ee&&z=0&&M<=z;){if(p=t[(n=M+z>>1)-1]||null,b=t[n],!p)return{lo:null,hi:b};if(b[e]o))return{lo:p,hi:b};z=n-1}}return{lo:b,hi:null}}function qp(t,e,o,n){var p=fp(t,e,o),b=p.lo?p.hi?p.lo:t[t.length-2]:t[0],M=p.lo?p.hi?p.hi:t[t.length-1]:t[1],z=M[e]-b[e],r=z?(o-b[e])/z:0,c=(M[n]-b[n])*r;return b[n]+c}function hp(t,e){var o=t._adapter,n=t.options.time,p=n.parser,b=p||n.format,M=e;return"function"==typeof p&&(M=p(M)),zt.isFinite(M)||(M="string"==typeof b?o.parse(M,b):o.parse(M)),null!==M?+M:(p||"function"!=typeof b||(M=b(e),zt.isFinite(M)||(M=o.parse(M))),M)}function Wp(t,e){if(zt.isNullOrUndef(e))return null;var o=t.options.time,n=hp(t,t.getRightValue(e));return null===n||o.round&&(n=+t._adapter.startOf(n,o.round)),n}function vp(t,e,o,n){var p,b,M,z=Op.length;for(p=Op.indexOf(t);p=Op.indexOf(o);b--)if(M=Op[b],ap[M].common&&t._adapter.diff(p,n,M)>=e-1)return M;return Op[o?Op.indexOf(o):0]}function mp(t){for(var e=Op.indexOf(t)+1,o=Op.length;e1e5*c)throw e+" and "+o+" are too far apart with stepSize of "+c+" "+r;for(p=a;p=0&&(e[b].major=!0);return e}function Lp(t,e,o){var n,p,b=[],M={},z=e.length;for(n=0;n1?lp(l).sort(sp):l.sort(sp),O=Math.min(O,l[0]),s=Math.max(s,l[l.length-1])),O=Wp(z,dp(i))||O,s=Wp(z,up(i))||s,O=O===ip?+c.startOf(Date.now(),a):O,s=s===cp?+c.endOf(Date.now(),a)+1:s,z.min=Math.min(O,s),z.max=Math.max(O+1,s),z._table=[],z._timestamps={data:l,datasets:d,labels:u}},buildTicks:function(){var t,e,o,n=this,p=n.min,b=n.max,M=n.options,z=M.ticks,r=M.time,c=n._timestamps,i=[],a=n.getLabelCapacity(p),O=z.source,s=M.distribution;for(c="data"===O||"auto"===O&&"series"===s?c.data:"labels"===O?c.labels:Rp(n,p,b,a),"ticks"===M.bounds&&c.length&&(p=c[0],b=c[c.length-1]),p=Wp(n,dp(M))||p,b=Wp(n,up(M))||b,t=0,e=c.length;t=p&&o<=b&&i.push(o);return n.min=p,n.max=b,n._unit=r.unit||(z.autoSkip?vp(r.minUnit,n.min,n.max,a):gp(n,i.length,r.minUnit,n.min,n.max)),n._majorUnit=z.major.enabled&&"year"!==n._unit?mp(n._unit):void 0,n._table=Ap(n._timestamps.data,p,b,s),n._offsets=yp(n._table,i,p,b,M),z.reverse&&i.reverse(),Lp(n,i,n._majorUnit)},getLabelForIndex:function(t,e){var o=this,n=o._adapter,p=o.chart.data,b=o.options.time,M=p.labels&&t=0&&t0?z:1}}),Np=Xp;_p._defaults=Np;var wp={category:gn,linear:Cn,logarithmic:In,radialLinear:pp,time:_p},xp={datetime:"MMM D, YYYY, h:mm:ss a",millisecond:"h:mm:ss.SSS a",second:"h:mm:ss a",minute:"h:mm a",hour:"hA",day:"MMM D",week:"ll",month:"MMM YYYY",quarter:"[Q]Q - YYYY",year:"YYYY"};Qo._date.override("function"==typeof t?{_id:"moment",formats:function(){return xp},parse:function(e,o){return"string"==typeof e&&"string"==typeof o?e=t(e,o):e instanceof t||(e=t(e)),e.isValid()?e.valueOf():null},format:function(e,o){return t(e).format(o)},add:function(e,o,n){return t(e).add(o,n).valueOf()},diff:function(e,o,n){return t(e).diff(t(o),n)},startOf:function(e,o,n){return e=t(e),"isoWeek"===o?e.isoWeekday(n).valueOf():e.startOf(o).valueOf()},endOf:function(e,o){return t(e).endOf(o).valueOf()},_create:function(e){return t(e)}}:{}),Q._set("global",{plugins:{filler:{propagate:!0}}});var Tp={dataset:function(t){var e=t.fill,o=t.chart,n=o.getDatasetMeta(e),p=n&&o.isDatasetVisible(e)&&n.dataset._children||[],b=p.length||0;return b?function(t,e){return e=o)&&n;switch(b){case"bottom":return"start";case"top":return"end";case"zero":return"origin";case"origin":case"start":case"end":return b;default:return!1}}function Sp(t){var e,o=t.el._model||{},n=t.el._scale||{},p=t.fill,b=null;if(isFinite(p))return null;if("start"===p?b=void 0===o.scaleBottom?n.bottom:o.scaleBottom:"end"===p?b=void 0===o.scaleTop?n.top:o.scaleTop:void 0!==o.scaleZero?b=o.scaleZero:n.getBasePixel&&(b=n.getBasePixel()),null!=b){if(void 0!==b.x&&void 0!==b.y)return b;if(zt.isFinite(b))return{x:(e=n.isHorizontal())?b:null,y:e?null:b}}return null}function kp(t){var e,o,n,p,b,M=t.el._scale,z=M.options,r=M.chart.data.labels.length,c=t.fill,i=[];if(!r)return null;for(e=z.ticks.reverse?M.max:M.min,o=z.ticks.reverse?M.min:M.max,n=M.getPointPositionForValue(0,e),p=0;p0;--b)zt.canvas.lineTo(t,o[b],o[b-1],!0);else for(M=o[0].cx,z=o[0].cy,r=Math.sqrt(Math.pow(o[0].x-M,2)+Math.pow(o[0].y-z,2)),b=p-1;b>0;--b)t.arc(M,z,r,o[b].angle,o[b-1].angle,!0)}}function Fp(t,e,o,n,p,b){var M,z,r,c,i,a,O,s,l=e.length,d=n.spanGaps,u=[],A=[],f=0,q=0;for(t.beginPath(),M=0,z=l;M=0;--o)(e=r[o].$filler)&&e.visible&&(p=(n=e.el)._view,b=n._children||[],M=e.mapper,z=p.backgroundColor||Q.global.defaultColor,M&&z&&b.length&&(zt.canvas.clipArea(c,t.chartArea),Fp(c,b,M,p,z,n._loop),zt.canvas.unclipArea(c)))}},Up=zt.rtl.getRtlAdapter,Vp=zt.noop,$p=zt.valueOrDefault;function Yp(t,e){return t.usePointStyle&&t.boxWidth>e?e:t.boxWidth}Q._set("global",{legend:{display:!0,position:"top",align:"center",fullWidth:!0,reverse:!1,weight:1e3,onClick:function(t,e){var o=e.datasetIndex,n=this.chart,p=n.getDatasetMeta(o);p.hidden=null===p.hidden?!n.data.datasets[o].hidden:null,n.update()},onHover:null,onLeave:null,labels:{boxWidth:40,padding:10,generateLabels:function(t){var e=t.data.datasets,o=t.options.legend||{},n=o.labels&&o.labels.usePointStyle;return t._getSortedDatasetMetas().map((function(o){var p=o.controller.getStyle(n?0:void 0);return{text:e[o.index].label,fillStyle:p.backgroundColor,hidden:!t.isDatasetVisible(o.index),lineCap:p.borderCapStyle,lineDash:p.borderDash,lineDashOffset:p.borderDashOffset,lineJoin:p.borderJoinStyle,lineWidth:p.borderWidth,strokeStyle:p.borderColor,pointStyle:p.pointStyle,rotation:p.rotation,datasetIndex:o.index}}),this)}}},legendCallback:function(t){var e,o,n,p=document.createElement("ul"),b=t.data.datasets;for(p.setAttribute("class",t.id+"-legend"),e=0,o=b.length;er.width)&&(a+=M+o.padding,i[i.length-(e>0?0:1)]=0),z[e]={left:0,top:0,width:n,height:M},i[i.length-1]+=n+o.padding})),r.height+=a}else{var O=o.padding,s=t.columnWidths=[],l=t.columnHeights=[],d=o.padding,u=0,A=0;zt.each(t.legendItems,(function(t,e){var n=Yp(o,M)+M/2+p.measureText(t.text).width;e>0&&A+M+2*O>r.height&&(d+=u+o.padding,s.push(u),l.push(A),u=0,A=0),u=Math.max(u,n),A+=M+O,z[e]={left:0,top:0,width:n,height:M}})),d+=u,s.push(u),l.push(A),r.width+=d}t.width=r.width,t.height=r.height}else t.width=r.width=t.height=r.height=0},afterFit:Vp,isHorizontal:function(){return"top"===this.options.position||"bottom"===this.options.position},draw:function(){var t=this,e=t.options,o=e.labels,n=Q.global,p=n.defaultColor,b=n.elements.line,M=t.height,z=t.columnHeights,r=t.width,c=t.lineWidths;if(e.display){var i,a=Up(e.rtl,t.left,t.minSize.width),O=t.ctx,s=$p(o.fontColor,n.defaultFontColor),l=zt.options._parseFont(o),d=l.size;O.textAlign=a.textAlign("left"),O.textBaseline="middle",O.lineWidth=.5,O.strokeStyle=s,O.fillStyle=s,O.font=l.string;var u=Yp(o,d),A=t.legendHitBoxes,f=function(t,e,n){if(!(isNaN(u)||u<=0)){O.save();var M=$p(n.lineWidth,b.borderWidth);if(O.fillStyle=$p(n.fillStyle,p),O.lineCap=$p(n.lineCap,b.borderCapStyle),O.lineDashOffset=$p(n.lineDashOffset,b.borderDashOffset),O.lineJoin=$p(n.lineJoin,b.borderJoinStyle),O.lineWidth=M,O.strokeStyle=$p(n.strokeStyle,p),O.setLineDash&&O.setLineDash($p(n.lineDash,b.borderDash)),o&&o.usePointStyle){var z=u*Math.SQRT2/2,r=a.xPlus(t,u/2),c=e+d/2;zt.canvas.drawPoint(O,n.pointStyle,z,r,c,n.rotation)}else O.fillRect(a.leftForLtr(t,u),e,u,d),0!==M&&O.strokeRect(a.leftForLtr(t,u),e,u,d);O.restore()}},q=function(t,e,o,n){var p=d/2,b=a.xPlus(t,u+p),M=e+p;O.fillText(o.text,b,M),o.hidden&&(O.beginPath(),O.lineWidth=2,O.moveTo(b,M),O.lineTo(a.xPlus(b,n),M),O.stroke())},h=function(t,n){switch(e.align){case"start":return o.padding;case"end":return t-n;default:return(t-n+o.padding)/2}},W=t.isHorizontal();i=W?{x:t.left+h(r,c[0]),y:t.top+o.padding,line:0}:{x:t.left+o.padding,y:t.top+h(M,z[0]),line:0},zt.rtl.overrideTextDirection(t.ctx,e.textDirection);var v=d+o.padding;zt.each(t.legendItems,(function(e,n){var p=O.measureText(e.text).width,b=u+d/2+p,s=i.x,l=i.y;a.setWidth(t.minSize.width),W?n>0&&s+b+o.padding>t.left+t.minSize.width&&(l=i.y+=v,i.line++,s=i.x=t.left+h(r,c[i.line])):n>0&&l+v>t.top+t.minSize.height&&(s=i.x=s+t.columnWidths[i.line]+o.padding,i.line++,l=i.y=t.top+h(M,z[i.line]));var g=a.x(s);f(g,l,e),A[n].left=a.leftForLtr(g,A[n].width),A[n].top=l,q(g,l,e,p),W?i.x+=b+o.padding:i.y+=v})),zt.rtl.restoreTextDirection(t.ctx,e.textDirection)}},_getLegendItemAt:function(t,e){var o,n,p,b=this;if(t>=b.left&&t<=b.right&&e>=b.top&&e<=b.bottom)for(p=b.legendHitBoxes,o=0;o=(n=p[o]).left&&t<=n.left+n.width&&e>=n.top&&e<=n.top+n.height)return b.legendItems[o];return null},handleEvent:function(t){var e,o=this,n=o.options,p="mouseup"===t.type?"click":t.type;if("mousemove"===p){if(!n.onHover&&!n.onLeave)return}else{if("click"!==p)return;if(!n.onClick)return}e=o._getLegendItemAt(t.x,t.y),"click"===p?e&&n.onClick&&n.onClick.call(o,t.native,e):(n.onLeave&&e!==o._hoveredItem&&(o._hoveredItem&&n.onLeave.call(o,t.native,o._hoveredItem),o._hoveredItem=e),n.onHover&&e&&n.onHover.call(o,t.native,e))}});function Jp(t,e){var o=new Gp({ctx:t.ctx,options:e,chart:t});Ue.configure(t,o,e),Ue.addBox(t,o),t.legend=o}var Kp={id:"legend",_element:Gp,beforeInit:function(t){var e=t.options.legend;e&&Jp(t,e)},beforeUpdate:function(t){var e=t.options.legend,o=t.legend;e?(zt.mergeIf(e,Q.global.legend),o?(Ue.configure(t,o,e),o.options=e):Jp(t,e)):o&&(Ue.removeBox(t,o),delete t.legend)},afterEvent:function(t,e){var o=t.legend;o&&o.handleEvent(e)}},Qp=zt.noop;Q._set("global",{title:{display:!1,fontStyle:"bold",fullWidth:!0,padding:10,position:"top",text:"",weight:2e3}});var Zp=dt.extend({initialize:function(t){var e=this;zt.extend(e,t),e.legendHitBoxes=[]},beforeUpdate:Qp,update:function(t,e,o){var n=this;return n.beforeUpdate(),n.maxWidth=t,n.maxHeight=e,n.margins=o,n.beforeSetDimensions(),n.setDimensions(),n.afterSetDimensions(),n.beforeBuildLabels(),n.buildLabels(),n.afterBuildLabels(),n.beforeFit(),n.fit(),n.afterFit(),n.afterUpdate(),n.minSize},afterUpdate:Qp,beforeSetDimensions:Qp,setDimensions:function(){var t=this;t.isHorizontal()?(t.width=t.maxWidth,t.left=0,t.right=t.width):(t.height=t.maxHeight,t.top=0,t.bottom=t.height),t.paddingLeft=0,t.paddingTop=0,t.paddingRight=0,t.paddingBottom=0,t.minSize={width:0,height:0}},afterSetDimensions:Qp,beforeBuildLabels:Qp,buildLabels:Qp,afterBuildLabels:Qp,beforeFit:Qp,fit:function(){var t,e=this,o=e.options,n=e.minSize={},p=e.isHorizontal();o.display?(t=(zt.isArray(o.text)?o.text.length:1)*zt.options._parseFont(o).lineHeight+2*o.padding,e.width=n.width=p?e.maxWidth:t,e.height=n.height=p?t:e.maxHeight):e.width=n.width=e.height=n.height=0},afterFit:Qp,isHorizontal:function(){var t=this.options.position;return"top"===t||"bottom"===t},draw:function(){var t=this,e=t.ctx,o=t.options;if(o.display){var n,p,b,M=zt.options._parseFont(o),z=M.lineHeight,r=z/2+o.padding,c=0,i=t.top,a=t.left,O=t.bottom,s=t.right;e.fillStyle=zt.valueOrDefault(o.fontColor,Q.global.defaultFontColor),e.font=M.string,t.isHorizontal()?(p=a+(s-a)/2,b=i+r,n=s-a):(p="left"===o.position?a+r:s-r,b=i+(O-i)/2,n=O-i,c=Math.PI*("left"===o.position?-.5:.5)),e.save(),e.translate(p,b),e.rotate(c),e.textAlign="center",e.textBaseline="middle";var l=o.text;if(zt.isArray(l))for(var d=0,u=0;u0&&e-1 in t)}m.fn=m.prototype={jquery:g,constructor:m,length:0,toArray:function(){return z.call(this)},get:function(t){return null==t?z.call(this):t<0?this[t+this.length]:this[t]},pushStack:function(t){var e=m.merge(this.constructor(),t);return e.prevObject=this,e},each:function(t){return m.each(this,t)},map:function(t){return this.pushStack(m.map(this,(function(e,o){return t.call(e,o,e)})))},slice:function(){return this.pushStack(z.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},even:function(){return this.pushStack(m.grep(this,(function(t,e){return(e+1)%2})))},odd:function(){return this.pushStack(m.grep(this,(function(t,e){return e%2})))},eq:function(t){var e=this.length,o=+t+(t<0?e:0);return this.pushStack(o>=0&&o+~]|[\\x20\\t\\r\\n\\f])[\\x20\\t\\r\\n\\f]*"),U=new RegExp(k+"|>"),V=new RegExp(P),$=new RegExp("^"+E+"$"),Y={ID:new RegExp("^#("+E+")"),CLASS:new RegExp("^\\.("+E+")"),TAG:new RegExp("^("+E+"|[*])"),ATTR:new RegExp("^"+D),PSEUDO:new RegExp("^"+P),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\([\\x20\\t\\r\\n\\f]*(even|odd|(([+-]|)(\\d*)n|)[\\x20\\t\\r\\n\\f]*(?:([+-]|)[\\x20\\t\\r\\n\\f]*(\\d+)|))[\\x20\\t\\r\\n\\f]*\\)|)","i"),bool:new RegExp("^(?:"+S+")$","i"),needsContext:new RegExp("^[\\x20\\t\\r\\n\\f]*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\([\\x20\\t\\r\\n\\f]*((?:-\\d)?\\d*)[\\x20\\t\\r\\n\\f]*\\)|)(?=[^-]|$)","i")},G=/HTML$/i,J=/^(?:input|select|textarea|button)$/i,K=/^h\d$/i,Q=/^[^{]+\{\s*\[native \w/,Z=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,tt=/[+~]/,et=new RegExp("\\\\[\\da-fA-F]{1,6}[\\x20\\t\\r\\n\\f]?|\\\\([^\\r\\n\\f])","g"),ot=function(t,e){var o="0x"+t.slice(1)-65536;return e||(o<0?String.fromCharCode(o+65536):String.fromCharCode(o>>10|55296,1023&o|56320))},nt=/([\0-\x1f\x7f]|^-?\d)|^-$|[^\0-\x1f\x7f-\uFFFF\w-]/g,pt=function(t,e){return e?"\0"===t?"�":t.slice(0,-1)+"\\"+t.charCodeAt(t.length-1).toString(16)+" ":"\\"+t},bt=function(){O()},Mt=ht((function(t){return!0===t.disabled&&"fieldset"===t.nodeName.toLowerCase()}),{dir:"parentNode",next:"legend"});try{x.apply(_=T.call(W.childNodes),W.childNodes),_[W.childNodes.length].nodeType}catch(t){x={apply:_.length?function(t,e){w.apply(t,T.call(e))}:function(t,e){for(var o=t.length,n=0;t[o++]=e[n++];);t.length=o-1}}}function zt(t,e,n,p){var b,z,c,i,a,l,A,f=e&&e.ownerDocument,W=e?e.nodeType:9;if(n=n||[],"string"!=typeof t||!t||1!==W&&9!==W&&11!==W)return n;if(!p&&(O(e),e=e||s,d)){if(11!==W&&(a=Z.exec(t)))if(b=a[1]){if(9===W){if(!(c=e.getElementById(b)))return n;if(c.id===b)return n.push(c),n}else if(f&&(c=f.getElementById(b))&&q(e,c)&&c.id===b)return n.push(c),n}else{if(a[2])return x.apply(n,e.getElementsByTagName(t)),n;if((b=a[3])&&o.getElementsByClassName&&e.getElementsByClassName)return x.apply(n,e.getElementsByClassName(b)),n}if(o.qsa&&!B[t+" "]&&(!u||!u.test(t))&&(1!==W||"object"!==e.nodeName.toLowerCase())){if(A=t,f=e,1===W&&(U.test(t)||H.test(t))){for((f=tt.test(t)&&At(e.parentNode)||e)===e&&o.scope||((i=e.getAttribute("id"))?i=i.replace(nt,pt):e.setAttribute("id",i=h)),z=(l=M(t)).length;z--;)l[z]=(i?"#"+i:":scope")+" "+qt(l[z]);A=l.join(",")}try{return x.apply(n,f.querySelectorAll(A)),n}catch(e){B(t,!0)}finally{i===h&&e.removeAttribute("id")}}}return r(t.replace(I,"$1"),e,n,p)}function rt(){var t=[];return function e(o,p){return t.push(o+" ")>n.cacheLength&&delete e[t.shift()],e[o+" "]=p}}function ct(t){return t[h]=!0,t}function it(t){var e=s.createElement("fieldset");try{return!!t(e)}catch(t){return!1}finally{e.parentNode&&e.parentNode.removeChild(e),e=null}}function at(t,e){for(var o=t.split("|"),p=o.length;p--;)n.attrHandle[o[p]]=e}function Ot(t,e){var o=e&&t,n=o&&1===t.nodeType&&1===e.nodeType&&t.sourceIndex-e.sourceIndex;if(n)return n;if(o)for(;o=o.nextSibling;)if(o===e)return-1;return t?1:-1}function st(t){return function(e){return"input"===e.nodeName.toLowerCase()&&e.type===t}}function lt(t){return function(e){var o=e.nodeName.toLowerCase();return("input"===o||"button"===o)&&e.type===t}}function dt(t){return function(e){return"form"in e?e.parentNode&&!1===e.disabled?"label"in e?"label"in e.parentNode?e.parentNode.disabled===t:e.disabled===t:e.isDisabled===t||e.isDisabled!==!t&&Mt(e)===t:e.disabled===t:"label"in e&&e.disabled===t}}function ut(t){return ct((function(e){return e=+e,ct((function(o,n){for(var p,b=t([],o.length,e),M=b.length;M--;)o[p=b[M]]&&(o[p]=!(n[p]=o[p]))}))}))}function At(t){return t&&void 0!==t.getElementsByTagName&&t}for(e in o=zt.support={},b=zt.isXML=function(t){var e=t&&t.namespaceURI,o=t&&(t.ownerDocument||t).documentElement;return!G.test(e||o&&o.nodeName||"HTML")},O=zt.setDocument=function(t){var e,p,M=t?t.ownerDocument||t:W;return M!=s&&9===M.nodeType&&M.documentElement?(l=(s=M).documentElement,d=!b(s),W!=s&&(p=s.defaultView)&&p.top!==p&&(p.addEventListener?p.addEventListener("unload",bt,!1):p.attachEvent&&p.attachEvent("onunload",bt)),o.scope=it((function(t){return l.appendChild(t).appendChild(s.createElement("div")),void 0!==t.querySelectorAll&&!t.querySelectorAll(":scope fieldset div").length})),o.attributes=it((function(t){return t.className="i",!t.getAttribute("className")})),o.getElementsByTagName=it((function(t){return t.appendChild(s.createComment("")),!t.getElementsByTagName("*").length})),o.getElementsByClassName=Q.test(s.getElementsByClassName),o.getById=it((function(t){return l.appendChild(t).id=h,!s.getElementsByName||!s.getElementsByName(h).length})),o.getById?(n.filter.ID=function(t){var e=t.replace(et,ot);return function(t){return t.getAttribute("id")===e}},n.find.ID=function(t,e){if(void 0!==e.getElementById&&d){var o=e.getElementById(t);return o?[o]:[]}}):(n.filter.ID=function(t){var e=t.replace(et,ot);return function(t){var o=void 0!==t.getAttributeNode&&t.getAttributeNode("id");return o&&o.value===e}},n.find.ID=function(t,e){if(void 0!==e.getElementById&&d){var o,n,p,b=e.getElementById(t);if(b){if((o=b.getAttributeNode("id"))&&o.value===t)return[b];for(p=e.getElementsByName(t),n=0;b=p[n++];)if((o=b.getAttributeNode("id"))&&o.value===t)return[b]}return[]}}),n.find.TAG=o.getElementsByTagName?function(t,e){return void 0!==e.getElementsByTagName?e.getElementsByTagName(t):o.qsa?e.querySelectorAll(t):void 0}:function(t,e){var o,n=[],p=0,b=e.getElementsByTagName(t);if("*"===t){for(;o=b[p++];)1===o.nodeType&&n.push(o);return n}return b},n.find.CLASS=o.getElementsByClassName&&function(t,e){if(void 0!==e.getElementsByClassName&&d)return e.getElementsByClassName(t)},A=[],u=[],(o.qsa=Q.test(s.querySelectorAll))&&(it((function(t){var e;l.appendChild(t).innerHTML="",t.querySelectorAll("[msallowcapture^='']").length&&u.push("[*^$]=[\\x20\\t\\r\\n\\f]*(?:''|\"\")"),t.querySelectorAll("[selected]").length||u.push("\\[[\\x20\\t\\r\\n\\f]*(?:value|"+S+")"),t.querySelectorAll("[id~="+h+"-]").length||u.push("~="),(e=s.createElement("input")).setAttribute("name",""),t.appendChild(e),t.querySelectorAll("[name='']").length||u.push("\\[[\\x20\\t\\r\\n\\f]*name[\\x20\\t\\r\\n\\f]*=[\\x20\\t\\r\\n\\f]*(?:''|\"\")"),t.querySelectorAll(":checked").length||u.push(":checked"),t.querySelectorAll("a#"+h+"+*").length||u.push(".#.+[+~]"),t.querySelectorAll("\\\f"),u.push("[\\r\\n\\f]")})),it((function(t){t.innerHTML="";var e=s.createElement("input");e.setAttribute("type","hidden"),t.appendChild(e).setAttribute("name","D"),t.querySelectorAll("[name=d]").length&&u.push("name[\\x20\\t\\r\\n\\f]*[*^$|!~]?="),2!==t.querySelectorAll(":enabled").length&&u.push(":enabled",":disabled"),l.appendChild(t).disabled=!0,2!==t.querySelectorAll(":disabled").length&&u.push(":enabled",":disabled"),t.querySelectorAll("*,:x"),u.push(",.*:")}))),(o.matchesSelector=Q.test(f=l.matches||l.webkitMatchesSelector||l.mozMatchesSelector||l.oMatchesSelector||l.msMatchesSelector))&&it((function(t){o.disconnectedMatch=f.call(t,"*"),f.call(t,"[s!='']:x"),A.push("!=",P)})),u=u.length&&new RegExp(u.join("|")),A=A.length&&new RegExp(A.join("|")),e=Q.test(l.compareDocumentPosition),q=e||Q.test(l.contains)?function(t,e){var o=9===t.nodeType?t.documentElement:t,n=e&&e.parentNode;return t===n||!(!n||1!==n.nodeType||!(o.contains?o.contains(n):t.compareDocumentPosition&&16&t.compareDocumentPosition(n)))}:function(t,e){if(e)for(;e=e.parentNode;)if(e===t)return!0;return!1},L=e?function(t,e){if(t===e)return a=!0,0;var n=!t.compareDocumentPosition-!e.compareDocumentPosition;return n||(1&(n=(t.ownerDocument||t)==(e.ownerDocument||e)?t.compareDocumentPosition(e):1)||!o.sortDetached&&e.compareDocumentPosition(t)===n?t==s||t.ownerDocument==W&&q(W,t)?-1:e==s||e.ownerDocument==W&&q(W,e)?1:i?C(i,t)-C(i,e):0:4&n?-1:1)}:function(t,e){if(t===e)return a=!0,0;var o,n=0,p=t.parentNode,b=e.parentNode,M=[t],z=[e];if(!p||!b)return t==s?-1:e==s?1:p?-1:b?1:i?C(i,t)-C(i,e):0;if(p===b)return Ot(t,e);for(o=t;o=o.parentNode;)M.unshift(o);for(o=e;o=o.parentNode;)z.unshift(o);for(;M[n]===z[n];)n++;return n?Ot(M[n],z[n]):M[n]==W?-1:z[n]==W?1:0},s):s},zt.matches=function(t,e){return zt(t,null,null,e)},zt.matchesSelector=function(t,e){if(O(t),o.matchesSelector&&d&&!B[e+" "]&&(!A||!A.test(e))&&(!u||!u.test(e)))try{var n=f.call(t,e);if(n||o.disconnectedMatch||t.document&&11!==t.document.nodeType)return n}catch(t){B(e,!0)}return zt(e,s,null,[t]).length>0},zt.contains=function(t,e){return(t.ownerDocument||t)!=s&&O(t),q(t,e)},zt.attr=function(t,e){(t.ownerDocument||t)!=s&&O(t);var p=n.attrHandle[e.toLowerCase()],b=p&&X.call(n.attrHandle,e.toLowerCase())?p(t,e,!d):void 0;return void 0!==b?b:o.attributes||!d?t.getAttribute(e):(b=t.getAttributeNode(e))&&b.specified?b.value:null},zt.escape=function(t){return(t+"").replace(nt,pt)},zt.error=function(t){throw new Error("Syntax error, unrecognized expression: "+t)},zt.uniqueSort=function(t){var e,n=[],p=0,b=0;if(a=!o.detectDuplicates,i=!o.sortStable&&t.slice(0),t.sort(L),a){for(;e=t[b++];)e===t[b]&&(p=n.push(b));for(;p--;)t.splice(n[p],1)}return i=null,t},p=zt.getText=function(t){var e,o="",n=0,b=t.nodeType;if(b){if(1===b||9===b||11===b){if("string"==typeof t.textContent)return t.textContent;for(t=t.firstChild;t;t=t.nextSibling)o+=p(t)}else if(3===b||4===b)return t.nodeValue}else for(;e=t[n++];)o+=p(e);return o},n=zt.selectors={cacheLength:50,createPseudo:ct,match:Y,attrHandle:{},find:{},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(t){return t[1]=t[1].replace(et,ot),t[3]=(t[3]||t[4]||t[5]||"").replace(et,ot),"~="===t[2]&&(t[3]=" "+t[3]+" "),t.slice(0,4)},CHILD:function(t){return t[1]=t[1].toLowerCase(),"nth"===t[1].slice(0,3)?(t[3]||zt.error(t[0]),t[4]=+(t[4]?t[5]+(t[6]||1):2*("even"===t[3]||"odd"===t[3])),t[5]=+(t[7]+t[8]||"odd"===t[3])):t[3]&&zt.error(t[0]),t},PSEUDO:function(t){var e,o=!t[6]&&t[2];return Y.CHILD.test(t[0])?null:(t[3]?t[2]=t[4]||t[5]||"":o&&V.test(o)&&(e=M(o,!0))&&(e=o.indexOf(")",o.length-e)-o.length)&&(t[0]=t[0].slice(0,e),t[2]=o.slice(0,e)),t.slice(0,3))}},filter:{TAG:function(t){var e=t.replace(et,ot).toLowerCase();return"*"===t?function(){return!0}:function(t){return t.nodeName&&t.nodeName.toLowerCase()===e}},CLASS:function(t){var e=m[t+" "];return e||(e=new RegExp("(^|[\\x20\\t\\r\\n\\f])"+t+"("+k+"|$)"))&&m(t,(function(t){return e.test("string"==typeof t.className&&t.className||void 0!==t.getAttribute&&t.getAttribute("class")||"")}))},ATTR:function(t,e,o){return function(n){var p=zt.attr(n,t);return null==p?"!="===e:!e||(p+="","="===e?p===o:"!="===e?p!==o:"^="===e?o&&0===p.indexOf(o):"*="===e?o&&p.indexOf(o)>-1:"$="===e?o&&p.slice(-o.length)===o:"~="===e?(" "+p.replace(j," ")+" ").indexOf(o)>-1:"|="===e&&(p===o||p.slice(0,o.length+1)===o+"-"))}},CHILD:function(t,e,o,n,p){var b="nth"!==t.slice(0,3),M="last"!==t.slice(-4),z="of-type"===e;return 1===n&&0===p?function(t){return!!t.parentNode}:function(e,o,r){var c,i,a,O,s,l,d=b!==M?"nextSibling":"previousSibling",u=e.parentNode,A=z&&e.nodeName.toLowerCase(),f=!r&&!z,q=!1;if(u){if(b){for(;d;){for(O=e;O=O[d];)if(z?O.nodeName.toLowerCase()===A:1===O.nodeType)return!1;l=d="only"===t&&!l&&"nextSibling"}return!0}if(l=[M?u.firstChild:u.lastChild],M&&f){for(q=(s=(c=(i=(a=(O=u)[h]||(O[h]={}))[O.uniqueID]||(a[O.uniqueID]={}))[t]||[])[0]===v&&c[1])&&c[2],O=s&&u.childNodes[s];O=++s&&O&&O[d]||(q=s=0)||l.pop();)if(1===O.nodeType&&++q&&O===e){i[t]=[v,s,q];break}}else if(f&&(q=s=(c=(i=(a=(O=e)[h]||(O[h]={}))[O.uniqueID]||(a[O.uniqueID]={}))[t]||[])[0]===v&&c[1]),!1===q)for(;(O=++s&&O&&O[d]||(q=s=0)||l.pop())&&((z?O.nodeName.toLowerCase()!==A:1!==O.nodeType)||!++q||(f&&((i=(a=O[h]||(O[h]={}))[O.uniqueID]||(a[O.uniqueID]={}))[t]=[v,q]),O!==e)););return(q-=p)===n||q%n==0&&q/n>=0}}},PSEUDO:function(t,e){var o,p=n.pseudos[t]||n.setFilters[t.toLowerCase()]||zt.error("unsupported pseudo: "+t);return p[h]?p(e):p.length>1?(o=[t,t,"",e],n.setFilters.hasOwnProperty(t.toLowerCase())?ct((function(t,o){for(var n,b=p(t,e),M=b.length;M--;)t[n=C(t,b[M])]=!(o[n]=b[M])})):function(t){return p(t,0,o)}):p}},pseudos:{not:ct((function(t){var e=[],o=[],n=z(t.replace(I,"$1"));return n[h]?ct((function(t,e,o,p){for(var b,M=n(t,null,p,[]),z=t.length;z--;)(b=M[z])&&(t[z]=!(e[z]=b))})):function(t,p,b){return e[0]=t,n(e,null,b,o),e[0]=null,!o.pop()}})),has:ct((function(t){return function(e){return zt(t,e).length>0}})),contains:ct((function(t){return t=t.replace(et,ot),function(e){return(e.textContent||p(e)).indexOf(t)>-1}})),lang:ct((function(t){return $.test(t||"")||zt.error("unsupported lang: "+t),t=t.replace(et,ot).toLowerCase(),function(e){var o;do{if(o=d?e.lang:e.getAttribute("xml:lang")||e.getAttribute("lang"))return(o=o.toLowerCase())===t||0===o.indexOf(t+"-")}while((e=e.parentNode)&&1===e.nodeType);return!1}})),target:function(e){var o=t.location&&t.location.hash;return o&&o.slice(1)===e.id},root:function(t){return t===l},focus:function(t){return t===s.activeElement&&(!s.hasFocus||s.hasFocus())&&!!(t.type||t.href||~t.tabIndex)},enabled:dt(!1),disabled:dt(!0),checked:function(t){var e=t.nodeName.toLowerCase();return"input"===e&&!!t.checked||"option"===e&&!!t.selected},selected:function(t){return t.parentNode&&t.parentNode.selectedIndex,!0===t.selected},empty:function(t){for(t=t.firstChild;t;t=t.nextSibling)if(t.nodeType<6)return!1;return!0},parent:function(t){return!n.pseudos.empty(t)},header:function(t){return K.test(t.nodeName)},input:function(t){return J.test(t.nodeName)},button:function(t){var e=t.nodeName.toLowerCase();return"input"===e&&"button"===t.type||"button"===e},text:function(t){var e;return"input"===t.nodeName.toLowerCase()&&"text"===t.type&&(null==(e=t.getAttribute("type"))||"text"===e.toLowerCase())},first:ut((function(){return[0]})),last:ut((function(t,e){return[e-1]})),eq:ut((function(t,e,o){return[o<0?o+e:o]})),even:ut((function(t,e){for(var o=0;oe?e:o;--n>=0;)t.push(n);return t})),gt:ut((function(t,e,o){for(var n=o<0?o+e:o;++n1?function(e,o,n){for(var p=t.length;p--;)if(!t[p](e,o,n))return!1;return!0}:t[0]}function vt(t,e,o,n,p){for(var b,M=[],z=0,r=t.length,c=null!=e;z-1&&(b[c]=!(M[c]=a))}}else A=vt(A===M?A.splice(l,A.length):A),p?p(null,M,A,r):x.apply(M,A)}))}function mt(t){for(var e,o,p,b=t.length,M=n.relative[t[0].type],z=M||n.relative[" "],r=M?1:0,i=ht((function(t){return t===e}),z,!0),a=ht((function(t){return C(e,t)>-1}),z,!0),O=[function(t,o,n){var p=!M&&(n||o!==c)||((e=o).nodeType?i(t,o,n):a(t,o,n));return e=null,p}];r1&&Wt(O),r>1&&qt(t.slice(0,r-1).concat({value:" "===t[r-2].type?"*":""})).replace(I,"$1"),o,r0,p=t.length>0,b=function(b,M,z,r,i){var a,l,u,A=0,f="0",q=b&&[],h=[],W=c,g=b||p&&n.find.TAG("*",i),m=v+=null==W?1:Math.random()||.1,R=g.length;for(i&&(c=M==s||M||i);f!==R&&null!=(a=g[f]);f++){if(p&&a){for(l=0,M||a.ownerDocument==s||(O(a),z=!d);u=t[l++];)if(u(a,M||s,z)){r.push(a);break}i&&(v=m)}o&&((a=!u&&a)&&A--,b&&q.push(a))}if(A+=f,o&&f!==A){for(l=0;u=e[l++];)u(q,h,M,z);if(b){if(A>0)for(;f--;)q[f]||h[f]||(h[f]=N.call(r));h=vt(h)}x.apply(r,h),i&&!b&&h.length>0&&A+e.length>1&&zt.uniqueSort(r)}return i&&(v=m,c=W),q};return o?ct(b):b}(b,p)),z.selector=t}return z},r=zt.select=function(t,e,o,p){var b,r,c,i,a,O="function"==typeof t&&t,s=!p&&M(t=O.selector||t);if(o=o||[],1===s.length){if((r=s[0]=s[0].slice(0)).length>2&&"ID"===(c=r[0]).type&&9===e.nodeType&&d&&n.relative[r[1].type]){if(!(e=(n.find.ID(c.matches[0].replace(et,ot),e)||[])[0]))return o;O&&(e=e.parentNode),t=t.slice(r.shift().value.length)}for(b=Y.needsContext.test(t)?0:r.length;b--&&(c=r[b],!n.relative[i=c.type]);)if((a=n.find[i])&&(p=a(c.matches[0].replace(et,ot),tt.test(r[0].type)&&At(e.parentNode)||e))){if(r.splice(b,1),!(t=p.length&&qt(r)))return x.apply(o,p),o;break}}return(O||z(t,s))(p,e,!d,o,!e||tt.test(t)&&At(e.parentNode)||e),o},o.sortStable=h.split("").sort(L).join("")===h,o.detectDuplicates=!!a,O(),o.sortDetached=it((function(t){return 1&t.compareDocumentPosition(s.createElement("fieldset"))})),it((function(t){return t.innerHTML="","#"===t.firstChild.getAttribute("href")}))||at("type|href|height|width",(function(t,e,o){if(!o)return t.getAttribute(e,"type"===e.toLowerCase()?1:2)})),o.attributes&&it((function(t){return t.innerHTML="",t.firstChild.setAttribute("value",""),""===t.firstChild.getAttribute("value")}))||at("value",(function(t,e,o){if(!o&&"input"===t.nodeName.toLowerCase())return t.defaultValue})),it((function(t){return null==t.getAttribute("disabled")}))||at(S,(function(t,e,o){var n;if(!o)return!0===t[e]?e.toLowerCase():(n=t.getAttributeNode(e))&&n.specified?n.value:null})),zt}(n);m.find=y,m.expr=y.selectors,m.expr[":"]=m.expr.pseudos,m.uniqueSort=m.unique=y.uniqueSort,m.text=y.getText,m.isXMLDoc=y.isXML,m.contains=y.contains,m.escapeSelector=y.escape;var B=function(t,e,o){for(var n=[],p=void 0!==o;(t=t[e])&&9!==t.nodeType;)if(1===t.nodeType){if(p&&m(t).is(o))break;n.push(t)}return n},L=function(t,e){for(var o=[];t;t=t.nextSibling)1===t.nodeType&&t!==e&&o.push(t);return o},X=m.expr.match.needsContext;function _(t,e){return t.nodeName&&t.nodeName.toLowerCase()===e.toLowerCase()}var N=/^<([a-z][^\/\0>:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i;function w(t,e,o){return A(e)?m.grep(t,(function(t,n){return!!e.call(t,n,t)!==o})):e.nodeType?m.grep(t,(function(t){return t===e!==o})):"string"!=typeof e?m.grep(t,(function(t){return i.call(e,t)>-1!==o})):m.filter(e,t,o)}m.filter=function(t,e,o){var n=e[0];return o&&(t=":not("+t+")"),1===e.length&&1===n.nodeType?m.find.matchesSelector(n,t)?[n]:[]:m.find.matches(t,m.grep(e,(function(t){return 1===t.nodeType})))},m.fn.extend({find:function(t){var e,o,n=this.length,p=this;if("string"!=typeof t)return this.pushStack(m(t).filter((function(){for(e=0;e1?m.uniqueSort(o):o},filter:function(t){return this.pushStack(w(this,t||[],!1))},not:function(t){return this.pushStack(w(this,t||[],!0))},is:function(t){return!!w(this,"string"==typeof t&&X.test(t)?m(t):t||[],!1).length}});var x,T=/^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]+))$/;(m.fn.init=function(t,e,o){var n,p;if(!t)return this;if(o=o||x,"string"==typeof t){if(!(n="<"===t[0]&&">"===t[t.length-1]&&t.length>=3?[null,t,null]:T.exec(t))||!n[1]&&e)return!e||e.jquery?(e||o).find(t):this.constructor(e).find(t);if(n[1]){if(e=e instanceof m?e[0]:e,m.merge(this,m.parseHTML(n[1],e&&e.nodeType?e.ownerDocument||e:q,!0)),N.test(n[1])&&m.isPlainObject(e))for(n in e)A(this[n])?this[n](e[n]):this.attr(n,e[n]);return this}return(p=q.getElementById(n[2]))&&(this[0]=p,this.length=1),this}return t.nodeType?(this[0]=t,this.length=1,this):A(t)?void 0!==o.ready?o.ready(t):t(m):m.makeArray(t,this)}).prototype=m.fn,x=m(q);var C=/^(?:parents|prev(?:Until|All))/,S={children:!0,contents:!0,next:!0,prev:!0};function k(t,e){for(;(t=t[e])&&1!==t.nodeType;);return t}m.fn.extend({has:function(t){var e=m(t,this),o=e.length;return this.filter((function(){for(var t=0;t-1:1===o.nodeType&&m.find.matchesSelector(o,t))){b.push(o);break}return this.pushStack(b.length>1?m.uniqueSort(b):b)},index:function(t){return t?"string"==typeof t?i.call(m(t),this[0]):i.call(this,t.jquery?t[0]:t):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(t,e){return this.pushStack(m.uniqueSort(m.merge(this.get(),m(t,e))))},addBack:function(t){return this.add(null==t?this.prevObject:this.prevObject.filter(t))}}),m.each({parent:function(t){var e=t.parentNode;return e&&11!==e.nodeType?e:null},parents:function(t){return B(t,"parentNode")},parentsUntil:function(t,e,o){return B(t,"parentNode",o)},next:function(t){return k(t,"nextSibling")},prev:function(t){return k(t,"previousSibling")},nextAll:function(t){return B(t,"nextSibling")},prevAll:function(t){return B(t,"previousSibling")},nextUntil:function(t,e,o){return B(t,"nextSibling",o)},prevUntil:function(t,e,o){return B(t,"previousSibling",o)},siblings:function(t){return L((t.parentNode||{}).firstChild,t)},children:function(t){return L(t.firstChild)},contents:function(t){return null!=t.contentDocument&&M(t.contentDocument)?t.contentDocument:(_(t,"template")&&(t=t.content||t),m.merge([],t.childNodes))}},(function(t,e){m.fn[t]=function(o,n){var p=m.map(this,e,o);return"Until"!==t.slice(-5)&&(n=o),n&&"string"==typeof n&&(p=m.filter(n,p)),this.length>1&&(S[t]||m.uniqueSort(p),C.test(t)&&p.reverse()),this.pushStack(p)}}));var E=/[^\x20\t\r\n\f]+/g;function D(t){return t}function P(t){throw t}function j(t,e,o,n){var p;try{t&&A(p=t.promise)?p.call(t).done(e).fail(o):t&&A(p=t.then)?p.call(t,e,o):e.apply(void 0,[t].slice(n))}catch(t){o.apply(void 0,[t])}}m.Callbacks=function(t){t="string"==typeof t?function(t){var e={};return m.each(t.match(E)||[],(function(t,o){e[o]=!0})),e}(t):m.extend({},t);var e,o,n,p,b=[],M=[],z=-1,r=function(){for(p=p||t.once,n=e=!0;M.length;z=-1)for(o=M.shift();++z-1;)b.splice(o,1),o<=z&&z--})),this},has:function(t){return t?m.inArray(t,b)>-1:b.length>0},empty:function(){return b&&(b=[]),this},disable:function(){return p=M=[],b=o="",this},disabled:function(){return!b},lock:function(){return p=M=[],o||e||(b=o=""),this},locked:function(){return!!p},fireWith:function(t,o){return p||(o=[t,(o=o||[]).slice?o.slice():o],M.push(o),e||r()),this},fire:function(){return c.fireWith(this,arguments),this},fired:function(){return!!n}};return c},m.extend({Deferred:function(t){var e=[["notify","progress",m.Callbacks("memory"),m.Callbacks("memory"),2],["resolve","done",m.Callbacks("once memory"),m.Callbacks("once memory"),0,"resolved"],["reject","fail",m.Callbacks("once memory"),m.Callbacks("once memory"),1,"rejected"]],o="pending",p={state:function(){return o},always:function(){return b.done(arguments).fail(arguments),this},catch:function(t){return p.then(null,t)},pipe:function(){var t=arguments;return m.Deferred((function(o){m.each(e,(function(e,n){var p=A(t[n[4]])&&t[n[4]];b[n[1]]((function(){var t=p&&p.apply(this,arguments);t&&A(t.promise)?t.promise().progress(o.notify).done(o.resolve).fail(o.reject):o[n[0]+"With"](this,p?[t]:arguments)}))})),t=null})).promise()},then:function(t,o,p){var b=0;function M(t,e,o,p){return function(){var z=this,r=arguments,c=function(){var n,c;if(!(t=b&&(o!==P&&(z=void 0,r=[n]),e.rejectWith(z,r))}};t?i():(m.Deferred.getStackHook&&(i.stackTrace=m.Deferred.getStackHook()),n.setTimeout(i))}}return m.Deferred((function(n){e[0][3].add(M(0,n,A(p)?p:D,n.notifyWith)),e[1][3].add(M(0,n,A(t)?t:D)),e[2][3].add(M(0,n,A(o)?o:P))})).promise()},promise:function(t){return null!=t?m.extend(t,p):p}},b={};return m.each(e,(function(t,n){var M=n[2],z=n[5];p[n[1]]=M.add,z&&M.add((function(){o=z}),e[3-t][2].disable,e[3-t][3].disable,e[0][2].lock,e[0][3].lock),M.add(n[3].fire),b[n[0]]=function(){return b[n[0]+"With"](this===b?void 0:this,arguments),this},b[n[0]+"With"]=M.fireWith})),p.promise(b),t&&t.call(b,b),b},when:function(t){var e=arguments.length,o=e,n=Array(o),p=z.call(arguments),b=m.Deferred(),M=function(t){return function(o){n[t]=this,p[t]=arguments.length>1?z.call(arguments):o,--e||b.resolveWith(n,p)}};if(e<=1&&(j(t,b.done(M(o)).resolve,b.reject,!e),"pending"===b.state()||A(p[o]&&p[o].then)))return b.then();for(;o--;)j(p[o],M(o),b.reject);return b.promise()}});var I=/^(Eval|Internal|Range|Reference|Syntax|Type|URI)Error$/;m.Deferred.exceptionHook=function(t,e){n.console&&n.console.warn&&t&&I.test(t.name)&&n.console.warn("jQuery.Deferred exception: "+t.message,t.stack,e)},m.readyException=function(t){n.setTimeout((function(){throw t}))};var F=m.Deferred();function H(){q.removeEventListener("DOMContentLoaded",H),n.removeEventListener("load",H),m.ready()}m.fn.ready=function(t){return F.then(t).catch((function(t){m.readyException(t)})),this},m.extend({isReady:!1,readyWait:1,ready:function(t){(!0===t?--m.readyWait:m.isReady)||(m.isReady=!0,!0!==t&&--m.readyWait>0||F.resolveWith(q,[m]))}}),m.ready.then=F.then,"complete"===q.readyState||"loading"!==q.readyState&&!q.documentElement.doScroll?n.setTimeout(m.ready):(q.addEventListener("DOMContentLoaded",H),n.addEventListener("load",H));var U=function(t,e,o,n,p,b,M){var z=0,r=t.length,c=null==o;if("object"===v(o))for(z in p=!0,o)U(t,e,z,o[z],!0,b,M);else if(void 0!==n&&(p=!0,A(n)||(M=!0),c&&(M?(e.call(t,n),e=null):(c=e,e=function(t,e,o){return c.call(m(t),o)})),e))for(;z1,null,!0)},removeData:function(t){return this.each((function(){Z.remove(this,t)}))}}),m.extend({queue:function(t,e,o){var n;if(t)return e=(e||"fx")+"queue",n=Q.get(t,e),o&&(!n||Array.isArray(o)?n=Q.access(t,e,m.makeArray(o)):n.push(o)),n||[]},dequeue:function(t,e){e=e||"fx";var o=m.queue(t,e),n=o.length,p=o.shift(),b=m._queueHooks(t,e);"inprogress"===p&&(p=o.shift(),n--),p&&("fx"===e&&o.unshift("inprogress"),delete b.stop,p.call(t,(function(){m.dequeue(t,e)}),b)),!n&&b&&b.empty.fire()},_queueHooks:function(t,e){var o=e+"queueHooks";return Q.get(t,o)||Q.access(t,o,{empty:m.Callbacks("once memory").add((function(){Q.remove(t,[e+"queue",o])}))})}}),m.fn.extend({queue:function(t,e){var o=2;return"string"!=typeof t&&(e=t,t="fx",o--),arguments.length\x20\t\r\n\f]*)/i,ft=/^$|^module$|\/(?:java|ecma)script/i;lt=q.createDocumentFragment().appendChild(q.createElement("div")),(dt=q.createElement("input")).setAttribute("type","radio"),dt.setAttribute("checked","checked"),dt.setAttribute("name","t"),lt.appendChild(dt),u.checkClone=lt.cloneNode(!0).cloneNode(!0).lastChild.checked,lt.innerHTML="",u.noCloneChecked=!!lt.cloneNode(!0).lastChild.defaultValue,lt.innerHTML="",u.option=!!lt.lastChild;var qt={thead:[1,"","
"],col:[2,"","
"],tr:[2,"","
"],td:[3,"","
"],_default:[0,"",""]};function ht(t,e){var o;return o=void 0!==t.getElementsByTagName?t.getElementsByTagName(e||"*"):void 0!==t.querySelectorAll?t.querySelectorAll(e||"*"):[],void 0===e||e&&_(t,e)?m.merge([t],o):o}function Wt(t,e){for(var o=0,n=t.length;o",""]);var vt=/<|&#?\w+;/;function gt(t,e,o,n,p){for(var b,M,z,r,c,i,a=e.createDocumentFragment(),O=[],s=0,l=t.length;s-1)p&&p.push(b);else if(c=zt(b),M=ht(a.appendChild(b),"script"),c&&Wt(M),o)for(i=0;b=M[i++];)ft.test(b.type||"")&&o.push(b);return a}var mt=/^([^.]*)(?:\.(.+)|)/;function Rt(){return!0}function yt(){return!1}function Bt(t,e){return t===function(){try{return q.activeElement}catch(t){}}()==("focus"===e)}function Lt(t,e,o,n,p,b){var M,z;if("object"==typeof e){for(z in"string"!=typeof o&&(n=n||o,o=void 0),e)Lt(t,z,o,n,e[z],b);return t}if(null==n&&null==p?(p=o,n=o=void 0):null==p&&("string"==typeof o?(p=n,n=void 0):(p=n,n=o,o=void 0)),!1===p)p=yt;else if(!p)return t;return 1===b&&(M=p,p=function(t){return m().off(t),M.apply(this,arguments)},p.guid=M.guid||(M.guid=m.guid++)),t.each((function(){m.event.add(this,e,p,n,o)}))}function Xt(t,e,o){o?(Q.set(t,e,!1),m.event.add(t,e,{namespace:!1,handler:function(t){var n,p,b=Q.get(this,e);if(1&t.isTrigger&&this[e]){if(b.length)(m.event.special[e]||{}).delegateType&&t.stopPropagation();else if(b=z.call(arguments),Q.set(this,e,b),n=o(this,e),this[e](),b!==(p=Q.get(this,e))||n?Q.set(this,e,!1):p={},b!==p)return t.stopImmediatePropagation(),t.preventDefault(),p&&p.value}else b.length&&(Q.set(this,e,{value:m.event.trigger(m.extend(b[0],m.Event.prototype),b.slice(1),this)}),t.stopImmediatePropagation())}})):void 0===Q.get(t,e)&&m.event.add(t,e,Rt)}m.event={global:{},add:function(t,e,o,n,p){var b,M,z,r,c,i,a,O,s,l,d,u=Q.get(t);if(J(t))for(o.handler&&(o=(b=o).handler,p=b.selector),p&&m.find.matchesSelector(Mt,p),o.guid||(o.guid=m.guid++),(r=u.events)||(r=u.events=Object.create(null)),(M=u.handle)||(M=u.handle=function(e){return void 0!==m&&m.event.triggered!==e.type?m.event.dispatch.apply(t,arguments):void 0}),c=(e=(e||"").match(E)||[""]).length;c--;)s=d=(z=mt.exec(e[c])||[])[1],l=(z[2]||"").split(".").sort(),s&&(a=m.event.special[s]||{},s=(p?a.delegateType:a.bindType)||s,a=m.event.special[s]||{},i=m.extend({type:s,origType:d,data:n,handler:o,guid:o.guid,selector:p,needsContext:p&&m.expr.match.needsContext.test(p),namespace:l.join(".")},b),(O=r[s])||((O=r[s]=[]).delegateCount=0,a.setup&&!1!==a.setup.call(t,n,l,M)||t.addEventListener&&t.addEventListener(s,M)),a.add&&(a.add.call(t,i),i.handler.guid||(i.handler.guid=o.guid)),p?O.splice(O.delegateCount++,0,i):O.push(i),m.event.global[s]=!0)},remove:function(t,e,o,n,p){var b,M,z,r,c,i,a,O,s,l,d,u=Q.hasData(t)&&Q.get(t);if(u&&(r=u.events)){for(c=(e=(e||"").match(E)||[""]).length;c--;)if(s=d=(z=mt.exec(e[c])||[])[1],l=(z[2]||"").split(".").sort(),s){for(a=m.event.special[s]||{},O=r[s=(n?a.delegateType:a.bindType)||s]||[],z=z[2]&&new RegExp("(^|\\.)"+l.join("\\.(?:.*\\.|)")+"(\\.|$)"),M=b=O.length;b--;)i=O[b],!p&&d!==i.origType||o&&o.guid!==i.guid||z&&!z.test(i.namespace)||n&&n!==i.selector&&("**"!==n||!i.selector)||(O.splice(b,1),i.selector&&O.delegateCount--,a.remove&&a.remove.call(t,i));M&&!O.length&&(a.teardown&&!1!==a.teardown.call(t,l,u.handle)||m.removeEvent(t,s,u.handle),delete r[s])}else for(s in r)m.event.remove(t,s+e[c],o,n,!0);m.isEmptyObject(r)&&Q.remove(t,"handle events")}},dispatch:function(t){var e,o,n,p,b,M,z=new Array(arguments.length),r=m.event.fix(t),c=(Q.get(this,"events")||Object.create(null))[r.type]||[],i=m.event.special[r.type]||{};for(z[0]=r,e=1;e=1))for(;c!==this;c=c.parentNode||this)if(1===c.nodeType&&("click"!==t.type||!0!==c.disabled)){for(b=[],M={},o=0;o-1:m.find(p,this,null,[c]).length),M[p]&&b.push(n);b.length&&z.push({elem:c,handlers:b})}return c=this,r\s*$/g;function xt(t,e){return _(t,"table")&&_(11!==e.nodeType?e:e.firstChild,"tr")&&m(t).children("tbody")[0]||t}function Tt(t){return t.type=(null!==t.getAttribute("type"))+"/"+t.type,t}function Ct(t){return"true/"===(t.type||"").slice(0,5)?t.type=t.type.slice(5):t.removeAttribute("type"),t}function St(t,e){var o,n,p,b,M,z;if(1===e.nodeType){if(Q.hasData(t)&&(z=Q.get(t).events))for(p in Q.remove(e,"handle events"),z)for(o=0,n=z[p].length;o1&&"string"==typeof l&&!u.checkClone&&Nt.test(l))return t.each((function(p){var b=t.eq(p);d&&(e[0]=l.call(this,p,b.html())),Et(b,e,o,n)}));if(O&&(b=(p=gt(e,t[0].ownerDocument,!1,t,n)).firstChild,1===p.childNodes.length&&(p=b),b||n)){for(z=(M=m.map(ht(p,"script"),Tt)).length;a0&&Wt(M,!r&&ht(t,"script")),z},cleanData:function(t){for(var e,o,n,p=m.event.special,b=0;void 0!==(o=t[b]);b++)if(J(o)){if(e=o[Q.expando]){if(e.events)for(n in e.events)p[n]?m.event.remove(o,n):m.removeEvent(o,n,e.handle);o[Q.expando]=void 0}o[Z.expando]&&(o[Z.expando]=void 0)}}}),m.fn.extend({detach:function(t){return Dt(this,t,!0)},remove:function(t){return Dt(this,t)},text:function(t){return U(this,(function(t){return void 0===t?m.text(this):this.empty().each((function(){1!==this.nodeType&&11!==this.nodeType&&9!==this.nodeType||(this.textContent=t)}))}),null,t,arguments.length)},append:function(){return Et(this,arguments,(function(t){1!==this.nodeType&&11!==this.nodeType&&9!==this.nodeType||xt(this,t).appendChild(t)}))},prepend:function(){return Et(this,arguments,(function(t){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var e=xt(this,t);e.insertBefore(t,e.firstChild)}}))},before:function(){return Et(this,arguments,(function(t){this.parentNode&&this.parentNode.insertBefore(t,this)}))},after:function(){return Et(this,arguments,(function(t){this.parentNode&&this.parentNode.insertBefore(t,this.nextSibling)}))},empty:function(){for(var t,e=0;null!=(t=this[e]);e++)1===t.nodeType&&(m.cleanData(ht(t,!1)),t.textContent="");return this},clone:function(t,e){return t=null!=t&&t,e=null==e?t:e,this.map((function(){return m.clone(this,t,e)}))},html:function(t){return U(this,(function(t){var e=this[0]||{},o=0,n=this.length;if(void 0===t&&1===e.nodeType)return e.innerHTML;if("string"==typeof t&&!_t.test(t)&&!qt[(At.exec(t)||["",""])[1].toLowerCase()]){t=m.htmlPrefilter(t);try{for(;o=0&&(r+=Math.max(0,Math.ceil(t["offset"+e[0].toUpperCase()+e.slice(1)]-b-r-z-.5))||0),r}function ne(t,e,o){var n=It(t),p=(!u.boxSizingReliable()||o)&&"border-box"===m.css(t,"boxSizing",!1,n),b=p,M=Vt(t,e,n),z="offset"+e[0].toUpperCase()+e.slice(1);if(Pt.test(M)){if(!o)return M;M="auto"}return(!u.boxSizingReliable()&&p||!u.reliableTrDimensions()&&_(t,"tr")||"auto"===M||!parseFloat(M)&&"inline"===m.css(t,"display",!1,n))&&t.getClientRects().length&&(p="border-box"===m.css(t,"boxSizing",!1,n),(b=z in t)&&(M=t[z])),(M=parseFloat(M)||0)+oe(t,e,o||(p?"border":"content"),b,n,M)+"px"}function pe(t,e,o,n,p){return new pe.prototype.init(t,e,o,n,p)}m.extend({cssHooks:{opacity:{get:function(t,e){if(e){var o=Vt(t,"opacity");return""===o?"1":o}}}},cssNumber:{animationIterationCount:!0,columnCount:!0,fillOpacity:!0,flexGrow:!0,flexShrink:!0,fontWeight:!0,gridArea:!0,gridColumn:!0,gridColumnEnd:!0,gridColumnStart:!0,gridRow:!0,gridRowEnd:!0,gridRowStart:!0,lineHeight:!0,opacity:!0,order:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{},style:function(t,e,o,n){if(t&&3!==t.nodeType&&8!==t.nodeType&&t.style){var p,b,M,z=G(e),r=jt.test(e),c=t.style;if(r||(e=Kt(z)),M=m.cssHooks[e]||m.cssHooks[z],void 0===o)return M&&"get"in M&&void 0!==(p=M.get(t,!1,n))?p:c[e];"string"===(b=typeof o)&&(p=pt.exec(o))&&p[1]&&(o=it(t,e,p),b="number"),null!=o&&o==o&&("number"!==b||r||(o+=p&&p[3]||(m.cssNumber[z]?"":"px")),u.clearCloneStyle||""!==o||0!==e.indexOf("background")||(c[e]="inherit"),M&&"set"in M&&void 0===(o=M.set(t,o,n))||(r?c.setProperty(e,o):c[e]=o))}},css:function(t,e,o,n){var p,b,M,z=G(e);return jt.test(e)||(e=Kt(z)),(M=m.cssHooks[e]||m.cssHooks[z])&&"get"in M&&(p=M.get(t,!0,o)),void 0===p&&(p=Vt(t,e,n)),"normal"===p&&e in te&&(p=te[e]),""===o||o?(b=parseFloat(p),!0===o||isFinite(b)?b||0:p):p}}),m.each(["height","width"],(function(t,e){m.cssHooks[e]={get:function(t,o,n){if(o)return!Qt.test(m.css(t,"display"))||t.getClientRects().length&&t.getBoundingClientRect().width?ne(t,e,n):Ft(t,Zt,(function(){return ne(t,e,n)}))},set:function(t,o,n){var p,b=It(t),M=!u.scrollboxSize()&&"absolute"===b.position,z=(M||n)&&"border-box"===m.css(t,"boxSizing",!1,b),r=n?oe(t,e,n,z,b):0;return z&&M&&(r-=Math.ceil(t["offset"+e[0].toUpperCase()+e.slice(1)]-parseFloat(b[e])-oe(t,e,"border",!1,b)-.5)),r&&(p=pt.exec(o))&&"px"!==(p[3]||"px")&&(t.style[e]=o,o=m.css(t,e)),ee(0,o,r)}}})),m.cssHooks.marginLeft=$t(u.reliableMarginLeft,(function(t,e){if(e)return(parseFloat(Vt(t,"marginLeft"))||t.getBoundingClientRect().left-Ft(t,{marginLeft:0},(function(){return t.getBoundingClientRect().left})))+"px"})),m.each({margin:"",padding:"",border:"Width"},(function(t,e){m.cssHooks[t+e]={expand:function(o){for(var n=0,p={},b="string"==typeof o?o.split(" "):[o];n<4;n++)p[t+bt[n]+e]=b[n]||b[n-2]||b[0];return p}},"margin"!==t&&(m.cssHooks[t+e].set=ee)})),m.fn.extend({css:function(t,e){return U(this,(function(t,e,o){var n,p,b={},M=0;if(Array.isArray(e)){for(n=It(t),p=e.length;M1)}}),m.Tween=pe,pe.prototype={constructor:pe,init:function(t,e,o,n,p,b){this.elem=t,this.prop=o,this.easing=p||m.easing._default,this.options=e,this.start=this.now=this.cur(),this.end=n,this.unit=b||(m.cssNumber[o]?"":"px")},cur:function(){var t=pe.propHooks[this.prop];return t&&t.get?t.get(this):pe.propHooks._default.get(this)},run:function(t){var e,o=pe.propHooks[this.prop];return this.options.duration?this.pos=e=m.easing[this.easing](t,this.options.duration*t,0,1,this.options.duration):this.pos=e=t,this.now=(this.end-this.start)*e+this.start,this.options.step&&this.options.step.call(this.elem,this.now,this),o&&o.set?o.set(this):pe.propHooks._default.set(this),this}},pe.prototype.init.prototype=pe.prototype,pe.propHooks={_default:{get:function(t){var e;return 1!==t.elem.nodeType||null!=t.elem[t.prop]&&null==t.elem.style[t.prop]?t.elem[t.prop]:(e=m.css(t.elem,t.prop,""))&&"auto"!==e?e:0},set:function(t){m.fx.step[t.prop]?m.fx.step[t.prop](t):1!==t.elem.nodeType||!m.cssHooks[t.prop]&&null==t.elem.style[Kt(t.prop)]?t.elem[t.prop]=t.now:m.style(t.elem,t.prop,t.now+t.unit)}}},pe.propHooks.scrollTop=pe.propHooks.scrollLeft={set:function(t){t.elem.nodeType&&t.elem.parentNode&&(t.elem[t.prop]=t.now)}},m.easing={linear:function(t){return t},swing:function(t){return.5-Math.cos(t*Math.PI)/2},_default:"swing"},m.fx=pe.prototype.init,m.fx.step={};var be,Me,ze=/^(?:toggle|show|hide)$/,re=/queueHooks$/;function ce(){Me&&(!1===q.hidden&&n.requestAnimationFrame?n.requestAnimationFrame(ce):n.setTimeout(ce,m.fx.interval),m.fx.tick())}function ie(){return n.setTimeout((function(){be=void 0})),be=Date.now()}function ae(t,e){var o,n=0,p={height:t};for(e=e?1:0;n<4;n+=2-e)p["margin"+(o=bt[n])]=p["padding"+o]=t;return e&&(p.opacity=p.width=t),p}function Oe(t,e,o){for(var n,p=(se.tweeners[e]||[]).concat(se.tweeners["*"]),b=0,M=p.length;b1)},removeAttr:function(t){return this.each((function(){m.removeAttr(this,t)}))}}),m.extend({attr:function(t,e,o){var n,p,b=t.nodeType;if(3!==b&&8!==b&&2!==b)return void 0===t.getAttribute?m.prop(t,e,o):(1===b&&m.isXMLDoc(t)||(p=m.attrHooks[e.toLowerCase()]||(m.expr.match.bool.test(e)?le:void 0)),void 0!==o?null===o?void m.removeAttr(t,e):p&&"set"in p&&void 0!==(n=p.set(t,o,e))?n:(t.setAttribute(e,o+""),o):p&&"get"in p&&null!==(n=p.get(t,e))?n:null==(n=m.find.attr(t,e))?void 0:n)},attrHooks:{type:{set:function(t,e){if(!u.radioValue&&"radio"===e&&_(t,"input")){var o=t.value;return t.setAttribute("type",e),o&&(t.value=o),e}}}},removeAttr:function(t,e){var o,n=0,p=e&&e.match(E);if(p&&1===t.nodeType)for(;o=p[n++];)t.removeAttribute(o)}}),le={set:function(t,e,o){return!1===e?m.removeAttr(t,o):t.setAttribute(o,o),o}},m.each(m.expr.match.bool.source.match(/\w+/g),(function(t,e){var o=de[e]||m.find.attr;de[e]=function(t,e,n){var p,b,M=e.toLowerCase();return n||(b=de[M],de[M]=p,p=null!=o(t,e,n)?M:null,de[M]=b),p}}));var ue=/^(?:input|select|textarea|button)$/i,Ae=/^(?:a|area)$/i;function fe(t){return(t.match(E)||[]).join(" ")}function qe(t){return t.getAttribute&&t.getAttribute("class")||""}function he(t){return Array.isArray(t)?t:"string"==typeof t&&t.match(E)||[]}m.fn.extend({prop:function(t,e){return U(this,m.prop,t,e,arguments.length>1)},removeProp:function(t){return this.each((function(){delete this[m.propFix[t]||t]}))}}),m.extend({prop:function(t,e,o){var n,p,b=t.nodeType;if(3!==b&&8!==b&&2!==b)return 1===b&&m.isXMLDoc(t)||(e=m.propFix[e]||e,p=m.propHooks[e]),void 0!==o?p&&"set"in p&&void 0!==(n=p.set(t,o,e))?n:t[e]=o:p&&"get"in p&&null!==(n=p.get(t,e))?n:t[e]},propHooks:{tabIndex:{get:function(t){var e=m.find.attr(t,"tabindex");return e?parseInt(e,10):ue.test(t.nodeName)||Ae.test(t.nodeName)&&t.href?0:-1}}},propFix:{for:"htmlFor",class:"className"}}),u.optSelected||(m.propHooks.selected={get:function(t){var e=t.parentNode;return e&&e.parentNode&&e.parentNode.selectedIndex,null},set:function(t){var e=t.parentNode;e&&(e.selectedIndex,e.parentNode&&e.parentNode.selectedIndex)}}),m.each(["tabIndex","readOnly","maxLength","cellSpacing","cellPadding","rowSpan","colSpan","useMap","frameBorder","contentEditable"],(function(){m.propFix[this.toLowerCase()]=this})),m.fn.extend({addClass:function(t){var e,o,n,p,b,M;return A(t)?this.each((function(e){m(this).addClass(t.call(this,e,qe(this)))})):(e=he(t)).length?this.each((function(){if(n=qe(this),o=1===this.nodeType&&" "+fe(n)+" "){for(b=0;b-1;)o=o.replace(" "+p+" "," ");M=fe(o),n!==M&&this.setAttribute("class",M)}})):this:this.attr("class","")},toggleClass:function(t,e){var o,n,p,b,M=typeof t,z="string"===M||Array.isArray(t);return A(t)?this.each((function(o){m(this).toggleClass(t.call(this,o,qe(this),e),e)})):"boolean"==typeof e&&z?e?this.addClass(t):this.removeClass(t):(o=he(t),this.each((function(){if(z)for(b=m(this),p=0;p-1)return!0;return!1}});var We=/\r/g;m.fn.extend({val:function(t){var e,o,n,p=this[0];return arguments.length?(n=A(t),this.each((function(o){var p;1===this.nodeType&&(null==(p=n?t.call(this,o,m(this).val()):t)?p="":"number"==typeof p?p+="":Array.isArray(p)&&(p=m.map(p,(function(t){return null==t?"":t+""}))),(e=m.valHooks[this.type]||m.valHooks[this.nodeName.toLowerCase()])&&"set"in e&&void 0!==e.set(this,p,"value")||(this.value=p))}))):p?(e=m.valHooks[p.type]||m.valHooks[p.nodeName.toLowerCase()])&&"get"in e&&void 0!==(o=e.get(p,"value"))?o:"string"==typeof(o=p.value)?o.replace(We,""):null==o?"":o:void 0}}),m.extend({valHooks:{option:{get:function(t){var e=m.find.attr(t,"value");return null!=e?e:fe(m.text(t))}},select:{get:function(t){var e,o,n,p=t.options,b=t.selectedIndex,M="select-one"===t.type,z=M?null:[],r=M?b+1:p.length;for(n=b<0?r:M?b:0;n-1)&&(o=!0);return o||(t.selectedIndex=-1),b}}}}),m.each(["radio","checkbox"],(function(){m.valHooks[this]={set:function(t,e){if(Array.isArray(e))return t.checked=m.inArray(m(t).val(),e)>-1}},u.checkOn||(m.valHooks[this].get=function(t){return null===t.getAttribute("value")?"on":t.value})})),u.focusin="onfocusin"in n;var ve=/^(?:focusinfocus|focusoutblur)$/,ge=function(t){t.stopPropagation()};m.extend(m.event,{trigger:function(t,e,o,p){var b,M,z,r,c,i,a,O,l=[o||q],d=s.call(t,"type")?t.type:t,u=s.call(t,"namespace")?t.namespace.split("."):[];if(M=O=z=o=o||q,3!==o.nodeType&&8!==o.nodeType&&!ve.test(d+m.event.triggered)&&(d.indexOf(".")>-1&&(u=d.split("."),d=u.shift(),u.sort()),c=d.indexOf(":")<0&&"on"+d,(t=t[m.expando]?t:new m.Event(d,"object"==typeof t&&t)).isTrigger=p?2:3,t.namespace=u.join("."),t.rnamespace=t.namespace?new RegExp("(^|\\.)"+u.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,t.result=void 0,t.target||(t.target=o),e=null==e?[t]:m.makeArray(e,[t]),a=m.event.special[d]||{},p||!a.trigger||!1!==a.trigger.apply(o,e))){if(!p&&!a.noBubble&&!f(o)){for(r=a.delegateType||d,ve.test(r+d)||(M=M.parentNode);M;M=M.parentNode)l.push(M),z=M;z===(o.ownerDocument||q)&&l.push(z.defaultView||z.parentWindow||n)}for(b=0;(M=l[b++])&&!t.isPropagationStopped();)O=M,t.type=b>1?r:a.bindType||d,(i=(Q.get(M,"events")||Object.create(null))[t.type]&&Q.get(M,"handle"))&&i.apply(M,e),(i=c&&M[c])&&i.apply&&J(M)&&(t.result=i.apply(M,e),!1===t.result&&t.preventDefault());return t.type=d,p||t.isDefaultPrevented()||a._default&&!1!==a._default.apply(l.pop(),e)||!J(o)||c&&A(o[d])&&!f(o)&&((z=o[c])&&(o[c]=null),m.event.triggered=d,t.isPropagationStopped()&&O.addEventListener(d,ge),o[d](),t.isPropagationStopped()&&O.removeEventListener(d,ge),m.event.triggered=void 0,z&&(o[c]=z)),t.result}},simulate:function(t,e,o){var n=m.extend(new m.Event,o,{type:t,isSimulated:!0});m.event.trigger(n,null,e)}}),m.fn.extend({trigger:function(t,e){return this.each((function(){m.event.trigger(t,e,this)}))},triggerHandler:function(t,e){var o=this[0];if(o)return m.event.trigger(t,e,o,!0)}}),u.focusin||m.each({focus:"focusin",blur:"focusout"},(function(t,e){var o=function(t){m.event.simulate(e,t.target,m.event.fix(t))};m.event.special[e]={setup:function(){var n=this.ownerDocument||this.document||this,p=Q.access(n,e);p||n.addEventListener(t,o,!0),Q.access(n,e,(p||0)+1)},teardown:function(){var n=this.ownerDocument||this.document||this,p=Q.access(n,e)-1;p?Q.access(n,e,p):(n.removeEventListener(t,o,!0),Q.remove(n,e))}}}));var me=n.location,Re={guid:Date.now()},ye=/\?/;m.parseXML=function(t){var e,o;if(!t||"string"!=typeof t)return null;try{e=(new n.DOMParser).parseFromString(t,"text/xml")}catch(t){}return o=e&&e.getElementsByTagName("parsererror")[0],e&&!o||m.error("Invalid XML: "+(o?m.map(o.childNodes,(function(t){return t.textContent})).join("\n"):t)),e};var Be=/\[\]$/,Le=/\r?\n/g,Xe=/^(?:submit|button|image|reset|file)$/i,_e=/^(?:input|select|textarea|keygen)/i;function Ne(t,e,o,n){var p;if(Array.isArray(e))m.each(e,(function(e,p){o||Be.test(t)?n(t,p):Ne(t+"["+("object"==typeof p&&null!=p?e:"")+"]",p,o,n)}));else if(o||"object"!==v(e))n(t,e);else for(p in e)Ne(t+"["+p+"]",e[p],o,n)}m.param=function(t,e){var o,n=[],p=function(t,e){var o=A(e)?e():e;n[n.length]=encodeURIComponent(t)+"="+encodeURIComponent(null==o?"":o)};if(null==t)return"";if(Array.isArray(t)||t.jquery&&!m.isPlainObject(t))m.each(t,(function(){p(this.name,this.value)}));else for(o in t)Ne(o,t[o],e,p);return n.join("&")},m.fn.extend({serialize:function(){return m.param(this.serializeArray())},serializeArray:function(){return this.map((function(){var t=m.prop(this,"elements");return t?m.makeArray(t):this})).filter((function(){var t=this.type;return this.name&&!m(this).is(":disabled")&&_e.test(this.nodeName)&&!Xe.test(t)&&(this.checked||!ut.test(t))})).map((function(t,e){var o=m(this).val();return null==o?null:Array.isArray(o)?m.map(o,(function(t){return{name:e.name,value:t.replace(Le,"\r\n")}})):{name:e.name,value:o.replace(Le,"\r\n")}})).get()}});var we=/%20/g,xe=/#.*$/,Te=/([?&])_=[^&]*/,Ce=/^(.*?):[ \t]*([^\r\n]*)$/gm,Se=/^(?:GET|HEAD)$/,ke=/^\/\//,Ee={},De={},Pe="*/".concat("*"),je=q.createElement("a");function Ie(t){return function(e,o){"string"!=typeof e&&(o=e,e="*");var n,p=0,b=e.toLowerCase().match(E)||[];if(A(o))for(;n=b[p++];)"+"===n[0]?(n=n.slice(1)||"*",(t[n]=t[n]||[]).unshift(o)):(t[n]=t[n]||[]).push(o)}}function Fe(t,e,o,n){var p={},b=t===De;function M(z){var r;return p[z]=!0,m.each(t[z]||[],(function(t,z){var c=z(e,o,n);return"string"!=typeof c||b||p[c]?b?!(r=c):void 0:(e.dataTypes.unshift(c),M(c),!1)})),r}return M(e.dataTypes[0])||!p["*"]&&M("*")}function He(t,e){var o,n,p=m.ajaxSettings.flatOptions||{};for(o in e)void 0!==e[o]&&((p[o]?t:n||(n={}))[o]=e[o]);return n&&m.extend(!0,t,n),t}je.href=me.href,m.extend({active:0,lastModified:{},etag:{},ajaxSettings:{url:me.href,type:"GET",isLocal:/^(?:about|app|app-storage|.+-extension|file|res|widget):$/.test(me.protocol),global:!0,processData:!0,async:!0,contentType:"application/x-www-form-urlencoded; charset=UTF-8",accepts:{"*":Pe,text:"text/plain",html:"text/html",xml:"application/xml, text/xml",json:"application/json, text/javascript"},contents:{xml:/\bxml\b/,html:/\bhtml/,json:/\bjson\b/},responseFields:{xml:"responseXML",text:"responseText",json:"responseJSON"},converters:{"* text":String,"text html":!0,"text json":JSON.parse,"text xml":m.parseXML},flatOptions:{url:!0,context:!0}},ajaxSetup:function(t,e){return e?He(He(t,m.ajaxSettings),e):He(m.ajaxSettings,t)},ajaxPrefilter:Ie(Ee),ajaxTransport:Ie(De),ajax:function(t,e){"object"==typeof t&&(e=t,t=void 0),e=e||{};var o,p,b,M,z,r,c,i,a,O,s=m.ajaxSetup({},e),l=s.context||s,d=s.context&&(l.nodeType||l.jquery)?m(l):m.event,u=m.Deferred(),A=m.Callbacks("once memory"),f=s.statusCode||{},h={},W={},v="canceled",g={readyState:0,getResponseHeader:function(t){var e;if(c){if(!M)for(M={};e=Ce.exec(b);)M[e[1].toLowerCase()+" "]=(M[e[1].toLowerCase()+" "]||[]).concat(e[2]);e=M[t.toLowerCase()+" "]}return null==e?null:e.join(", ")},getAllResponseHeaders:function(){return c?b:null},setRequestHeader:function(t,e){return null==c&&(t=W[t.toLowerCase()]=W[t.toLowerCase()]||t,h[t]=e),this},overrideMimeType:function(t){return null==c&&(s.mimeType=t),this},statusCode:function(t){var e;if(t)if(c)g.always(t[g.status]);else for(e in t)f[e]=[f[e],t[e]];return this},abort:function(t){var e=t||v;return o&&o.abort(e),R(0,e),this}};if(u.promise(g),s.url=((t||s.url||me.href)+"").replace(ke,me.protocol+"//"),s.type=e.method||e.type||s.method||s.type,s.dataTypes=(s.dataType||"*").toLowerCase().match(E)||[""],null==s.crossDomain){r=q.createElement("a");try{r.href=s.url,r.href=r.href,s.crossDomain=je.protocol+"//"+je.host!=r.protocol+"//"+r.host}catch(t){s.crossDomain=!0}}if(s.data&&s.processData&&"string"!=typeof s.data&&(s.data=m.param(s.data,s.traditional)),Fe(Ee,s,e,g),c)return g;for(a in(i=m.event&&s.global)&&0==m.active++&&m.event.trigger("ajaxStart"),s.type=s.type.toUpperCase(),s.hasContent=!Se.test(s.type),p=s.url.replace(xe,""),s.hasContent?s.data&&s.processData&&0===(s.contentType||"").indexOf("application/x-www-form-urlencoded")&&(s.data=s.data.replace(we,"+")):(O=s.url.slice(p.length),s.data&&(s.processData||"string"==typeof s.data)&&(p+=(ye.test(p)?"&":"?")+s.data,delete s.data),!1===s.cache&&(p=p.replace(Te,"$1"),O=(ye.test(p)?"&":"?")+"_="+Re.guid+++O),s.url=p+O),s.ifModified&&(m.lastModified[p]&&g.setRequestHeader("If-Modified-Since",m.lastModified[p]),m.etag[p]&&g.setRequestHeader("If-None-Match",m.etag[p])),(s.data&&s.hasContent&&!1!==s.contentType||e.contentType)&&g.setRequestHeader("Content-Type",s.contentType),g.setRequestHeader("Accept",s.dataTypes[0]&&s.accepts[s.dataTypes[0]]?s.accepts[s.dataTypes[0]]+("*"!==s.dataTypes[0]?", "+Pe+"; q=0.01":""):s.accepts["*"]),s.headers)g.setRequestHeader(a,s.headers[a]);if(s.beforeSend&&(!1===s.beforeSend.call(l,g,s)||c))return g.abort();if(v="abort",A.add(s.complete),g.done(s.success),g.fail(s.error),o=Fe(De,s,e,g)){if(g.readyState=1,i&&d.trigger("ajaxSend",[g,s]),c)return g;s.async&&s.timeout>0&&(z=n.setTimeout((function(){g.abort("timeout")}),s.timeout));try{c=!1,o.send(h,R)}catch(t){if(c)throw t;R(-1,t)}}else R(-1,"No Transport");function R(t,e,M,r){var a,O,q,h,W,v=e;c||(c=!0,z&&n.clearTimeout(z),o=void 0,b=r||"",g.readyState=t>0?4:0,a=t>=200&&t<300||304===t,M&&(h=function(t,e,o){for(var n,p,b,M,z=t.contents,r=t.dataTypes;"*"===r[0];)r.shift(),void 0===n&&(n=t.mimeType||e.getResponseHeader("Content-Type"));if(n)for(p in z)if(z[p]&&z[p].test(n)){r.unshift(p);break}if(r[0]in o)b=r[0];else{for(p in o){if(!r[0]||t.converters[p+" "+r[0]]){b=p;break}M||(M=p)}b=b||M}if(b)return b!==r[0]&&r.unshift(b),o[b]}(s,g,M)),!a&&m.inArray("script",s.dataTypes)>-1&&m.inArray("json",s.dataTypes)<0&&(s.converters["text script"]=function(){}),h=function(t,e,o,n){var p,b,M,z,r,c={},i=t.dataTypes.slice();if(i[1])for(M in t.converters)c[M.toLowerCase()]=t.converters[M];for(b=i.shift();b;)if(t.responseFields[b]&&(o[t.responseFields[b]]=e),!r&&n&&t.dataFilter&&(e=t.dataFilter(e,t.dataType)),r=b,b=i.shift())if("*"===b)b=r;else if("*"!==r&&r!==b){if(!(M=c[r+" "+b]||c["* "+b]))for(p in c)if((z=p.split(" "))[1]===b&&(M=c[r+" "+z[0]]||c["* "+z[0]])){!0===M?M=c[p]:!0!==c[p]&&(b=z[0],i.unshift(z[1]));break}if(!0!==M)if(M&&t.throws)e=M(e);else try{e=M(e)}catch(t){return{state:"parsererror",error:M?t:"No conversion from "+r+" to "+b}}}return{state:"success",data:e}}(s,h,g,a),a?(s.ifModified&&((W=g.getResponseHeader("Last-Modified"))&&(m.lastModified[p]=W),(W=g.getResponseHeader("etag"))&&(m.etag[p]=W)),204===t||"HEAD"===s.type?v="nocontent":304===t?v="notmodified":(v=h.state,O=h.data,a=!(q=h.error))):(q=v,!t&&v||(v="error",t<0&&(t=0))),g.status=t,g.statusText=(e||v)+"",a?u.resolveWith(l,[O,v,g]):u.rejectWith(l,[g,v,q]),g.statusCode(f),f=void 0,i&&d.trigger(a?"ajaxSuccess":"ajaxError",[g,s,a?O:q]),A.fireWith(l,[g,v]),i&&(d.trigger("ajaxComplete",[g,s]),--m.active||m.event.trigger("ajaxStop")))}return g},getJSON:function(t,e,o){return m.get(t,e,o,"json")},getScript:function(t,e){return m.get(t,void 0,e,"script")}}),m.each(["get","post"],(function(t,e){m[e]=function(t,o,n,p){return A(o)&&(p=p||n,n=o,o=void 0),m.ajax(m.extend({url:t,type:e,dataType:p,data:o,success:n},m.isPlainObject(t)&&t))}})),m.ajaxPrefilter((function(t){var e;for(e in t.headers)"content-type"===e.toLowerCase()&&(t.contentType=t.headers[e]||"")})),m._evalUrl=function(t,e,o){return m.ajax({url:t,type:"GET",dataType:"script",cache:!0,async:!1,global:!1,converters:{"text script":function(){}},dataFilter:function(t){m.globalEval(t,e,o)}})},m.fn.extend({wrapAll:function(t){var e;return this[0]&&(A(t)&&(t=t.call(this[0])),e=m(t,this[0].ownerDocument).eq(0).clone(!0),this[0].parentNode&&e.insertBefore(this[0]),e.map((function(){for(var t=this;t.firstElementChild;)t=t.firstElementChild;return t})).append(this)),this},wrapInner:function(t){return A(t)?this.each((function(e){m(this).wrapInner(t.call(this,e))})):this.each((function(){var e=m(this),o=e.contents();o.length?o.wrapAll(t):e.append(t)}))},wrap:function(t){var e=A(t);return this.each((function(o){m(this).wrapAll(e?t.call(this,o):t)}))},unwrap:function(t){return this.parent(t).not("body").each((function(){m(this).replaceWith(this.childNodes)})),this}}),m.expr.pseudos.hidden=function(t){return!m.expr.pseudos.visible(t)},m.expr.pseudos.visible=function(t){return!!(t.offsetWidth||t.offsetHeight||t.getClientRects().length)},m.ajaxSettings.xhr=function(){try{return new n.XMLHttpRequest}catch(t){}};var Ue={0:200,1223:204},Ve=m.ajaxSettings.xhr();u.cors=!!Ve&&"withCredentials"in Ve,u.ajax=Ve=!!Ve,m.ajaxTransport((function(t){var e,o;if(u.cors||Ve&&!t.crossDomain)return{send:function(p,b){var M,z=t.xhr();if(z.open(t.type,t.url,t.async,t.username,t.password),t.xhrFields)for(M in t.xhrFields)z[M]=t.xhrFields[M];for(M in t.mimeType&&z.overrideMimeType&&z.overrideMimeType(t.mimeType),t.crossDomain||p["X-Requested-With"]||(p["X-Requested-With"]="XMLHttpRequest"),p)z.setRequestHeader(M,p[M]);e=function(t){return function(){e&&(e=o=z.onload=z.onerror=z.onabort=z.ontimeout=z.onreadystatechange=null,"abort"===t?z.abort():"error"===t?"number"!=typeof z.status?b(0,"error"):b(z.status,z.statusText):b(Ue[z.status]||z.status,z.statusText,"text"!==(z.responseType||"text")||"string"!=typeof z.responseText?{binary:z.response}:{text:z.responseText},z.getAllResponseHeaders()))}},z.onload=e(),o=z.onerror=z.ontimeout=e("error"),void 0!==z.onabort?z.onabort=o:z.onreadystatechange=function(){4===z.readyState&&n.setTimeout((function(){e&&o()}))},e=e("abort");try{z.send(t.hasContent&&t.data||null)}catch(t){if(e)throw t}},abort:function(){e&&e()}}})),m.ajaxPrefilter((function(t){t.crossDomain&&(t.contents.script=!1)})),m.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/\b(?:java|ecma)script\b/},converters:{"text script":function(t){return m.globalEval(t),t}}}),m.ajaxPrefilter("script",(function(t){void 0===t.cache&&(t.cache=!1),t.crossDomain&&(t.type="GET")})),m.ajaxTransport("script",(function(t){var e,o;if(t.crossDomain||t.scriptAttrs)return{send:function(n,p){e=m("