Added Notifications

This commit is contained in:
2026-05-11 23:00:48 +10:00
parent c7fe3268c7
commit 69d72e0912
28 changed files with 2094 additions and 23 deletions
@@ -203,6 +203,7 @@ class UpdateDepartedFlights extends Command
'user_id' => $flight->user_id,
'title' => "Flight {$airlineCode}{$flightNumber} updated",
'body' => implode("\n", $changeDescriptions),
'url' => '/u/'. $flight->user->name . '/flight/'. $flight->id,
]);
} else {
$this->info("No changes for {$airlineCode}{$flightNumber}");
@@ -211,6 +212,7 @@ class UpdateDepartedFlights extends Command
'user_id' => $flight->user_id,
'title' => "Flight {$airlineCode}{$flightNumber} updated — no changes",
'body' => "Your flight was completed and no updates were made to aircraft, registration, or departure/arrival times.",
'url' => '/u/'. $flight->user->name . '/flight/'. $flight->id,
]);
}
@@ -3,6 +3,7 @@
namespace App\Http\Controllers;
use App\Models\Achievement;
use App\Models\Country;
use App\Models\User;
use Illuminate\Http\Request;
use Inertia\Inertia;
@@ -30,4 +31,25 @@ class AchievementController extends Controller
'userAchievements' => $userAchievements,
]);
}
public function specific(User $user, Achievement $achievement)
{
$regions = match($achievement->internal_name){
'fun_challenges.australian_states' => Country::where('code', 'AU')->first()->regions->toArray(),
'fun_challenges.chinese_provinces' => Country::where('code', 'CN')->first()->regions->toArray(),
'fun_challenges.canadian_provinces' => Country::where('code', 'CA')->first()->regions->toArray(),
'fun_challenges.us_states' => Country::where('code', 'US')->first()->regions->toArray(),
default => [],
};
return Inertia::render('Profile/UserAchievement', [
'user' => $user,
'achievement' => $achievement,
'userAchievement' => $user->achievements()->where('achievement_id', $achievement->id)->first(),
'isFollowing' => auth()->check() && auth()->user()->isFollowing($user),
'flight_api_url' => FlightProfileController::getUserFlightApiURL($user),
'regions' => $regions,
]);
}
}
@@ -10,13 +10,17 @@ use Inertia\Inertia;
class FlightProfileController extends Controller
{
public static function getUserFlightApiURL(User $user){
return '/data/user/'.$user->name.'/flights';
}
public function profileData(User $user, string $view, ?int $selectedFlightId = null) : array {
return [
'user' => $user,
'canEdit' => auth()->check() && auth()->id() === $user->id,
'initialView' => $view,
'selectedFlightId' => $selectedFlightId,
'flight_api_url' => '/data/user/'.$user->name.'/flights',
'flight_api_url' => self::getUserFlightApiURL($user),
'isFollowing' => auth()->check() && auth()->user()->isFollowing($user),
];
}
+8
View File
@@ -39,13 +39,21 @@ class Achievement extends Model
'achievement_category_id',
'achievement_difficulty_id',
'threshold',
'has_page',
];
protected $casts = [
'has_page' => 'boolean',
'progressive' => 'boolean',
'threshold' => 'integer',
];
public function getRouteKeyName(): string
{
return 'internal_name';
}
// ---------------------------------------------------------------
// Relationships
// ---------------------------------------------------------------
@@ -0,0 +1,47 @@
<?php
use App\Models\Achievement;
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::table('achievements', function (Blueprint $table) {
$table->boolean('has_page')->default(false);
});
$achievements = [
'airlines_alliances.all_skyteam',
'airlines_alliances.all_oneworld',
'airlines_alliances.all_star_alliance',
'airlines_alliances.all_vanilla_alliance',
'fun_challenges.airline_alphabet',
'fun_challenges.airport_alphabet',
'fun_challenges.brazilian_states',
'fun_challenges.us_states',
'fun_challenges.australian_states',
'fun_challenges.chinese_provinces',
'fun_challenges.canadian_provinces',
'countries_continents.all_continent_pairs_one_way',
'countries_continents.all_continent_pairs_both_ways',
];
foreach($achievements as $achievement) {
Achievement::where('internal_name', $achievement)->update(['has_page' => true]);
}
}
/**
* Reverse the migrations.
*/
public function down(): void
{
//
}
};
@@ -1,13 +1,15 @@
<!-- AchievementCard.vue -->
<script setup lang="ts">
import {Achievement, BadgeVariant, UserAchievement} from "@/Types/types";
import {Achievement, BadgeVariant, User, UserAchievement} from "@/Types/types";
import {computed} from "vue";
import InlineBadge from "@/Components/FlightsGoneBy/InlineBadge.vue";
import GlassTooltip from "@/Components/FlightsGoneBy/GlassTooltip.vue";
import {Link} from '@inertiajs/vue3'
const props = defineProps<{
achievement: Achievement
userAchievement?: UserAchievement
user?: User
}>()
const progress = computed(() => {
@@ -83,6 +85,9 @@ const difficultyVariant = computed(() => {
</div>
<p class="achievement-description">{{ achievement.short_description }}</p>
<Link v-if="achievement.has_page && user" :href="route('profile.achievement', { user: user.name, achievement: achievement.internal_name })">
View Details
</Link>
<template v-if="achievement.progressive && progress">
<div class="progress-label">
@@ -11,6 +11,7 @@ const page = usePage<SharedProps>().props;
const props = defineProps<{
airline: Airline | null;
size?: number | string;
hideTooltip?: boolean;
}>();
const logoUrl = computed(() => `url('${props.airline?.logo_url ?? page.logo_api_url+'/airline/undefined/logo/tail'}')`);
@@ -26,7 +27,7 @@ const size = computed(() => props.size ? props.size + 'px' : '30px');
</script>
<template>
<GlassTooltip>
<GlassTooltip v-if="!hideTooltip">
<template #activator="{ props: tooltipProps }">
<span class="airline-logo" v-bind="tooltipProps"></span>
</template>
@@ -54,6 +55,7 @@ const size = computed(() => props.size ? props.size + 'px' : '30px');
</div>
</div>
</GlassTooltip>
<span v-else class="airline-logo"></span>
</template>
<style scoped>
@@ -0,0 +1,49 @@
<script setup lang="ts">
import {Flight} from "@/Types/types";
import FlightToolTip from "@/Components/FlightsGoneBy/FlightToolTip.vue";
import AirlineLogo from "@/Components/FlightsGoneBy/AirlineLogo.vue";
import InlineBadge from "@/Components/FlightsGoneBy/InlineBadge.vue";
defineProps<{
regionCodes: string[]
flightsByRegion: Record<string, Flight[]>
regionNames?: Record<string, string>
}>()
</script>
<template>
<table>
<tr v-for="code in regionCodes" :key="code">
<td>{{ regionNames?.[code] ?? code }}</td>
<td>
<template v-if="flightsByRegion[code]?.length">
<span style="display:inline-flex; align-items:center; gap:0.25em; flex-wrap:wrap;">
<FlightToolTip
v-for="(flight, index) in flightsByRegion[code].slice(0, 5)"
:key="flight.id"
:flight="flight"
>
<InlineBadge style="display:inline-flex; align-items:center; gap:0.25em;">
<AirlineLogo hideTooltip :airline="flight.airline" />
{{ flight.flight_number || `${flight.departure_airport.display_code}-${flight.arrival_airport.display_code}` }}
</InlineBadge>
</FlightToolTip>
</span>
</template>
<template v-else>
</template>
</td>
</tr>
</table>
</template>
<style scoped>
table {
border-spacing: 0;
width: 100%;
}
table td {
border: solid 1px;
padding: 0.5em;
}
</style>
@@ -0,0 +1,118 @@
<script setup lang="ts">
import { Flight } from "@/Types/types";
import GlassTooltip from "@/Components/FlightsGoneBy/GlassTooltip.vue";
import InlineBadge from "@/Components/FlightsGoneBy/InlineBadge.vue";
import AirlineLogo from "@/Components/FlightsGoneBy/AirlineLogo.vue";
import FlightMap from "@/Components/FlightsGoneBy/FlightMap.vue";
defineProps<{
flight: Flight
}>()
</script>
<template>
<GlassTooltip>
<template #activator="{ props: tooltipProps }">
<div style="display:inline; cursor:pointer" v-bind="tooltipProps">
<slot />
</div>
</template>
<div class="tooltip-header">
<span class="designator">
<AirlineLogo hideTooltip :airline="flight.airline" size="24" />
{{ flight.flight_number || `${flight.departure_airport.display_code}-${flight.arrival_airport.display_code}` }}
</span>
</div>
<div class="tooltip-name">
<InlineBadge variant="generic">{{ flight.departure_airport.display_code }}</InlineBadge>
<span class="arrow"></span>
<InlineBadge variant="generic">{{ flight.arrival_airport.display_code }}</InlineBadge>
</div>
<div class="tooltip-divider" />
<div class="tooltip-rows">
<div class="tooltip-row">
<span class="tooltip-label">From</span>
<span class="tooltip-value">{{ flight.departure_airport.municipality }}</span>
</div>
<div class="tooltip-row">
<span class="tooltip-label">To</span>
<span class="tooltip-value">{{ flight.arrival_airport.municipality }}</span>
</div>
<div class="tooltip-row" v-if="flight.airline">
<span class="tooltip-label">Airline</span>
<span class="tooltip-value">{{ flight.airline.name }}</span>
</div>
<div class="tooltip-row" v-if="flight.aircraft">
<span class="tooltip-label">Aircraft</span>
<span class="tooltip-value">{{ flight.aircraft?.display_name_short }}</span>
</div>
<div class="tooltip-row">
<span class="tooltip-label">Date</span>
<span class="tooltip-value">{{ flight.departure_date_display }}</span>
</div>
</div>
</GlassTooltip>
</template>
<style scoped>
.tooltip-header {
display: flex;
align-items: center;
justify-content: space-between;
gap: 0.75rem;
}
.designator {
display:inline-flex;
color: #e8eaf0;
}
.tooltip-name {
display: flex;
align-items: center;
gap: 4px;
margin-top: 0.2rem;
line-height: 1.3;
}
.arrow {
font-size: 0.75rem;
color: var(--muted, #445566);
}
.tooltip-divider {
height: 1px;
background: var(--table-border, rgba(255,255,255,0.08));
}
.tooltip-rows {
display: flex;
flex-direction: column;
gap: 0.3rem;
}
.tooltip-row {
display: flex;
align-items: baseline;
justify-content: space-between;
gap: 1rem;
}
.tooltip-label {
font-family: 'Share Tech Mono', monospace;
font-size: 0.6rem;
letter-spacing: 0.15em;
color: var(--muted, #445566);
flex-shrink: 0;
}
.tooltip-value {
font-size: 0.78rem;
color: var(--text, #c8cdd8);
text-align: right;
}
</style>
@@ -1,9 +1,11 @@
<script setup lang="ts">
defineProps<{
centered?: boolean
}>()
</script>
<template>
<div class="panel-header"><slot /></div>
<div class="panel-header" :style="`${centered ? 'text-align:center' : ''}`"><slot /></div>
</template>
<style scoped>
@@ -0,0 +1,38 @@
<script setup lang="ts">
defineProps<{
visitedRegions: Set<string>
stateLocalCodes: string[]
regionNames?: Record<string, string>
}>()
</script>
<template>
<div class="legend">
<v-chip
v-for="state in stateLocalCodes"
:key="state"
:color="visitedRegions.has(state) ? '#4a90d9' : 'grey'"
variant="flat"
size="small"
>
<template #prepend>
<v-icon
:icon="visitedRegions.has(state) ? 'mdi-check-circle' : 'mdi-circle-outline'"
size="small"
class="mr-1"
/>
</template>
{{ regionNames?.[state] ?? state }}
</v-chip>
</div>
</template>
<style scoped>
.legend {
display: flex;
flex-wrap: wrap;
gap: 8px;
justify-content: center;
margin-top: 12px;
}
</style>
@@ -2,6 +2,7 @@
import { usePage } from "@inertiajs/vue3";
import { computed, ref } from "vue";
import type { Flight, User, SharedProps } from "@/Types/types";
import { Link } from "@inertiajs/vue3";
const props = defineProps<{
user: User
@@ -42,7 +43,11 @@ const follow = async () => {
<div class="board-title-group">
<span class="board-eyebrow">FLIGHT HISTORY</span>
<div class="board-title-row">
<h1 class="board-title">{{ user.name }}</h1>
<h1 class="board-title">
<Link :href="route('profile.view', { user: user.name })">
{{ user.name }}
</Link>
</h1>
<button
v-if="isLoggedIn && !isOwnProfile"
class="follow-btn"
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+188
View File
@@ -0,0 +1,188 @@
<script setup lang="ts">
const props = defineProps<{
visitedRegions: Set<string>
}>()
</script>
<template>
<svg viewBox="-10 0 1050 850" xmlns="http://www.w3.org/2000/svg">
<!-- <g
id="layer3"
class="disputed"
style="display:inline;fill-opacity:1;fill:#e8e8e8;stroke:#808080;stroke-width:0.5">
<path id="AksaiChin" style="fill:#e8e8e8;fill-opacity:1" d="m76.224,451.63 0.631,-2.72 -0.253,-0.88 0.316,-1.27 0.632,-0.18 1.325,0.5 0.505,-0.13 -0.189,-1.89 0.316,-0.63 -0.758,-1.2 -0.06,-2.46 -0.505,-1.01 0.757,-0.82 1.263,-0.45 1.642,0.89 0.947,-0.44 1.262,0.31 1.2,0.1 2.778,0.89 0.694,-0.63 1.705,-1.27 -0.126,-1.26 0.379,-0.57 0.694,0.45 0.316,-0.76 0.06,-3.35 0.252,-0.88 0.884,-0.32 1.831,1.01 1.326,-0.5 -0.253,-1.64 0.316,-0.57 2.084,-0.19 1.073,-1.83 2.972,0.63 0.44,-0.38 1.26,-2.27 1.64,-1.39 0.95,-3.73 0.1,-1.45 2.27,-1.77 0.45,-0.94 -0.19,-1.46 0.56,-1.01 1.71,-0.94 0.82,-2.09 -0.63,-0.44 -1.07,0.1 -0.95,-1.19 -0.76,-0.1 -0.95,1.71 -1.83,1.01 -0.75,-0.57 v-2.72 l-0.89,-1.89 -1.2,1.01 -0.69,-0.32 -0.25,-1.45 -1.84,-0.63 -0.31,-1.7 -0.317,-1.14 0.757,-0.69 -0.32,-0.83 -0.627,-0.12 -0.126,-0.82 -1.578,0.12 -0.947,-0.75 0.442,-1.58 -0.442,-0.7 -1.452,-0.56 -1.579,0.31 -1.01,0.1 -1.389,-0.44 -3.662,0.7 -1.389,-1.14 -1.389,-0.38 -1.136,0.25 -0.821,1.27 -2.967,0.88 -1.389,-0.13 -1.263,0.7 -1.325,0.1 -1.389,1.07 -1.137,0.1 -1.01,0.69 -0.442,1.01 -0.694,-0.12 -1.453,-0.95 h-0.631 l-0.757,0.88 h-1.666 l0.456,0.94 3.104,-0.32 0.568,0.64 -1.705,2.96 -0.568,1.77 1.136,4.23 0.127,1.58 -0.19,2.21 0.695,1.58 0.252,2.59 -0.252,1.45 1.01,2.27 2.02,0.88 3.346,1.46 1.452,1.83 0.695,1.39 1.894,1.13 0.758,1.33 -0.442,2.4 -1.2,1.07 -3.977,0.63 -0.442,2.09 0.126,2.08 0.252,2.21 -0.315,1.7 -1.01,3.67 0.947,3.72z"/>
<g id="pTW">
<path id="pTW_1" d="m883.26,721.47 2.33,-0.71 0.53,-4.82 -1.07,-4.47 1.25,-5.89 3.57,-5.71 1.97,-6.79 1.07,-6.43 0.71,-18.39 0.72,-5.54 0.89,-1.42 v-3.75 l-1.25,-1.43 -1.07,-2.86 1.78,-2.86 0.72,-1.6 -1.25,-1.43 -3.57,-0.9 h-1.61 l-1.79,-2.14 h-2.5 l-1.25,1.97 0.54,2.14 -4.29,1.61 -3.03,2.5 -1.43,3.21 -0.54,3.93 -2.32,2.5 -1.61,5.89 -1.78,5.18 -2.68,6.25 -1.43,5.18 -0.53,5.53 0.35,5.18 1.43,2.32 2.14,3.22 1.97,5.71 2.5,3.4 3.03,1.25 2.86,0.71 2.32,3.04 1.43,3.75 v2.14z"/>
<path id="pTW_2" d="m826.3,673.26 1.96,0.36 -0.89,1.43 h-1.96z"/>
<path id="pTW_3" d="m803.82,761.15 -0.63,0.88 h1.52 l0.5,-0.75z"/>
</g>
<g id="Kashmir" style="stroke:none">
<path id="Kash_302" d="m77.49,471.85 1.199,-0.19 2.336,-1.26 1.547,-3.03 -1.547,-5.18 1.168,-2.52 -0.6,-1.77 -2.178,-0.95 -0.537,1.45 -0.789,0.98 -0.284,0.89 0.505,0.85 0.821,0.35 0.568,1.92 -0.536,1.3 -0.663,0.41 0.473,0.97 0.03,0.89 -0.663,1.51 0.252,0.89 -0.883,1.07z"/>
<path id="Kash_304" d="m62.088,475.82 -1.263,0.38 0.09,1.7 0.789,-0.22 1.231,2.09 1.358,2.27 0.378,1.92 1.074,-1.35 -0.62,-1.6 -2.032,-2.54z"/>
<path id="Kash_306" d="m64.929,497.25 0.915,1.87 0.06,1.8 0.536,1.1 2.967,1.23 h1.295 l1.041,0.1 -2.178,-7.29 -1.673,-0.44 -1.894,1.33z"/>
<path id="Kash_308" d="m87.633,515.59 -1.01,-1.77 -1.452,0.1 -0.978,-1.1 -0.19,1.45 -0.09,0.94 1.042,0.41 0.884,1.17z"/>
</g>
<path id="SouthTibet" style="stroke:none" d="m300.72,635.09 3.84,0.13 3.88,-0.71 2.99,-0.98 2.73,2.05 3.39,0.14 3.48,0.75 3.4,-0.44 1.69,0.31 0.98,-0.27 4.2,-0.8 2.37,-0.58 0.76,-3.35 3.08,-2.86 2.72,-1.65 2.86,-3.08 4.01,-0.76 6.83,-1.38 3,-1.88 2.5,-0.62 2.09,-1.25 2.1,-0.81 1.25,-3.48 11.43,-3.52 0.63,1.38 1.65,1.07 h2.77 l1.74,-0.72 1.29,2.15 1.43,0.22 0.45,-0.49 3.52,2.85 3.93,3.26 2.81,1.07 1.39,1.57 0.13,1.34 6.83,-4.42 0.58,-1.88 -0.62,-2.5 0.62,-1.96 -1.78,-0.14 -3.17,-3.08 -1.74,0.18 -0.85,0.49 -1.12,-0.44 -1.03,-0.63 -1.38,0.18 -1.96,-1.52 -2.15,-0.85 -2.41,0.9 -1.69,1.16 -2.06,-1.61 1.79,-0.85 -0.18,-1.11 0.45,-1.12 2.01,-0.94 0.17,-1.25 2.37,-1.2 0.1,-2.01 -1.12,-1.7 -0.8,-1.78 0.36,-1.66 h-0.99 l-2.81,1.12 -1.96,1.74 h-0.98 l0.1,-2.15 -0.18,-1.25 4.1,-2 1.08,-1.79 -0.67,-0.71 -2.15,0.66 -1.38,-1.25 -1.79,-3.43 -9.51,3.97 -1.2,2.68 -2.46,1.74 -2.99,-0.54 -0.94,-1.2 -7.45,-2.32 -0.31,-0.94 -2.55,-2.5 -1.87,1.7 -1.57,0.62 -2.9,1.12 -1.43,1.11 -2.27,2.19 -1.92,0.31 -0.14,2.1 -6.65,3.22 -7.72,0.13 -1.92,0.67 -1.56,4.51 -6.61,4.42 -0.85,-0.45 -2.59,2.1 0.98,1.38 -0.84,1.7 -5,2.23 h-2.64 l-0.85,-1.16 -0.71,0.85 -2.46,0.1 -1.56,1.25 -2.19,-0.1 -4.95,-1.74 -1.83,3.93 0.98,2.81 1.92,2.01 4.55,0.23 1.52,1.6 -0.22,1.97 -1.83,2.32 v2.14 l1.16,0.9 0.63,2.27z"/>
</g>-->
<g
id="layer4"
class="province"
style="fill-opacity:1; stroke:#000000; stroke-width:1">
<path id="pHJ" :class="{ visited: visitedRegions.has('23') }" d="m770,26.125 19.69,-6.906 7.22,-2.313 16.68,5.719 5.41,-2.375 8.31,2.562 6.78,5.625 1,2.5 4.94,3.469 3.69,6.188 0.97,4.062 10.09,12.906 0.47,4.188 9.19,9.156 1.15,7.344 3.94,2.187 0.28,5.563 6.13,6.437 6.65,-0.187 5.78,-3.469 8.47,3.938 3.69,-1.844 14.72,7.937 5.72,-1.25 1.4,5.878 5.54,6.25 -1.07,4.5 5.5,4.72 1.6,2.4 6.97,-2.59 5,-0.44 10.15,-4.53 1.41,-4.44 6.15,-6.9 4.16,-0.47 2.78,-4.128 7.81,-6.875 6.04,0.938 0.1,7.25 4.56,4.965 -1.47,6.88 -3.69,2.69 1.57,16.65 -0.6,3.31 1.63,6.1 -1.6,3.37 -1,13.57 -2.93,3.09 1.06,9.12 -1.75,1.1 -14.56,0.4 -3.19,-1.62 -4.22,9.62 -5.59,3.72 0.1,1.44 9.25,14.81 0.72,10.6 1.31,2.03 -4.5,2.06 -4.87,-2.62 -3.16,-0.52 -3.31,-5.86 -3.38,3.14 -2.87,-2.37 -2.06,0.47 -0.33,3.82 -4.58,1.3 -2.88,2.09 0.68,3.24 -1.3,2.44 -3.92,0.7 -3.89,-4.69 -0.25,-1.31 -3.69,-1 -3.8,-4.24 -0.72,-6.09 -1.82,-2.08 -3.77,-0.1 -0.62,2.77 2.07,7.09 -0.61,1.99 -2.57,1.19 -6.64,-6.41 -0.66,-3.48 -2.86,-1.35 -1.7,1.22 -2.58,0.55 -2.56,-3 0.96,-2.92 -3.26,-4.58 h-3.09 l-2.46,-1.66 -2.2,0.27 -3.36,3.79 -6.22,-0.53 -2.64,-1.54 -0.1,-2.41 -1.33,-1.14 -2.89,0.48 -1.85,2.99 -3.82,0.53 -2.43,-1.77 -1.93,1.74 -3.75,1.86 -2.77,-0.77 -6.25,-4.92 -2.31,-4.72 0.39,-2.03 -1.8,-2.72 -2.19,-1.45 -5.67,1.98 -3.25,0.33 -2.11,1.03 -2.45,-0.44 -0.67,-1.4 0.7,-2.81 -0.87,-2.13 0.84,-1.53 4.5,-0.23 1.98,-1.65 0.79,-2.39 -0.68,-1.53 -0.86,1.96 -1.98,0.51 -3.97,-0.69 -1.67,-0.89 -4.03,-4.06 -2.33,-0.51 -4.19,-4.43 0.6,-4.11 8.47,-8.29 0.81,-3.71 3.2,-3.03 6.7,-11.68 1.61,-1.04 1.11,0.32 1.78,4.01 2.16,2.13 0.63,-1 -0.13,-2.78 -0.75,-1.83 -0.44,-8.13 1.46,-8.79 1.46,-0.82 2.63,-0.39 1.06,-6.03 -3.08,-4.764 0.46,-2.703 -1.1,-2.937 -0.62,-5.938 2.12,-1.516 0.21,-4.406 3.51,-4.219 v-2.562 l-1.54,-1.516 0.12,-2.156 1.95,-2.328 0.47,-2.391 -1.28,-3.328 -2.56,-0.359 -7.89,-8.11 -5.19,-0.14 -1.67,4.828 -1.63,2.859 -3.84,0.09 -1.75,1.969 -3.34,-0.438 -1.61,1.297 -2.05,0.172 -1.63,3.172 -2.01,-0.156 -1.81,-1.313 -1.75,1.141 -3.11,-0.36 -3.85,-2.64 -3.78,-6.297 v-3.516 l-2.01,-3.922 -0.1,-1.625 0.37,-1.437 -0.98,-0.953 -2.8,-0.485 -2.53,-3.031 -1.65,-0.844 -1.71,0.813 -0.18,3.484 -1.77,1.578 -1.72,0.09 -2,-2.453 -3.09,-0.641 -4.57,-2.14 0.33,-1.75 4.69,-6.906 0.89,-3 -1.37,-2.266z">
<title>Heilongjiang Province</title>
</path>
<path id="pJL" :class="{ visited: visitedRegions.has('22') }" d="m824.59,181.91 2.32,-1.25 3.25,-0.13 5.5,-2.09 1.93,1.15 2.16,2.94 -0.63,2.09 2.54,4.88 6.07,4.78 2.61,0.89 3.96,-1.89 1.75,-1.7 2.97,1.83 3.54,-0.57 1.85,-3.11 2.79,-0.46 1.39,1.01 v2.3 l2.58,1.81 6.14,0.39 3.37,-3.64 2.05,-0.28 2.81,1.69 3.1,-0.1 3.26,4.28 -0.95,2.89 2.31,3.09 3.1,-0.48 1.37,-1.16 2.77,1.27 0.5,3.26 6.64,6.96 2.65,-1.27 0.88,-2.01 -2.2,-7.22 0.43,-2.63 3.85,0.1 1.82,1.83 0.88,6.2 3.58,4.33 3.81,0.78 0.38,1.55 3.76,4.7 3.86,-0.75 1.41,-2.31 -0.63,-3.19 2.61,-2.34 4.74,-1.13 0.35,-3.84 2.24,-0.42 2.58,2.21 3.51,-2.87 3.39,5.67 3.13,0.6 4.78,2.46 5.83,-2.43 v8.76 l-2.89,6.89 -4.99,3.13 -0.37,2.23 1.47,1.71 -2.89,0.26 -6.39,-6.33 -3.16,1.35 -0.39,12.62 -6.27,2.97 -0.4,5.34 -6.55,4.91 -8.12,1.45 -1.19,3.21 5.47,6.45 -0.64,4.09 -15.21,1.41 -5.81,-4.53 -5.97,3.94 -0.36,8.07 -7.29,12.21 -2.1,0.62 -1.5,-2.22 0.88,-2.59 -0.32,-4.22 -4.68,-4.37 -2.5,-3.29 -1.69,-0.37 -2.03,-4.16 1.78,-4.75 -0.28,-2.28 -2.47,-0.31 -5.81,-7.66 -2.16,-1.18 -0.41,-2.41 -2.28,-1.44 -0.68,-4.19 -1.32,-1.15 -1.9,1.59 -1.03,3.44 -2.1,1.31 -1.19,-1.22 -0.1,-2.81 -2.97,-3.19 -4.53,-1.28 -3.9,-2.06 -0.85,0.59 -0.1,2.25 -5.06,-1.47 -1.04,-0.9 -0.1,-1.66 1.56,-1.28 v-0.97 l-2.5,-5.59 -2.22,-1.72 -0.16,-2.97 -1.16,-0.56 -3.09,-4.22 -0.62,-1.97 -1.13,0.34 -8.47,7.54 -2,0.9 -2.94,-1.65 1.35,-1.97 -1.22,-2.44 -3.59,-3.28 -1.32,-6.25 -0.75,-1.91 0.57,-2 1.93,-1.72 0.35,-2.93 -2,-2.41 -2.66,-1.09 -1.19,-2.82 -1.43,-0.97 -2.35,0.5 -1.06,-1.12 0.87,-2.38 v-3.28 l3.16,-0.59 4.5,2.94 1.06,-1.69 1.1,-0.5 2.03,1 1.75,1.84 1.34,0.1 0.84,-1.69 -0.12,-3.25 -0.78,-1.66 0.37,-1.97 2.44,-0.5 1.13,-1.06z">
<title>Jilin Province</title>
</path>
<g id="pLN" :class="{ visited: visitedRegions.has('21') }">
<title>Liaoning Province</title>
<path id="pLN_1" d="m798.71,329.04 -2.05,-1.07 -0.75,-3.31 -2.85,-2.07 -0.97,-3.78 -5.34,-0.62 -1.78,-2.22 -3.13,0.28 -3.25,-3.59 1.91,-2.19 -0.16,-2.94 2.5,-2.59 -0.12,-1.75 2.37,-2.72 0.44,-2.88 -2.28,-3.03 -0.66,-3.12 v-7.1 l-1.93,-2.03 -0.19,-1.75 3.41,-3.28 2.96,2.69 h3 l0.1,1.81 3.69,4.1 1.37,3.37 1,0.47 0.81,-2.78 3.94,-5.19 1.28,-2.31 3.91,-3.44 3.5,-0.59 4.15,-6.1 1.88,-0.97 3,0.66 2.94,-1.75 -0.28,-3.25 1.78,-1.03 2.47,-0.44 2.25,0.53 1.78,-1.4 -1.47,-2 0.4,-1.44 h3.5 l2.6,1.69 5.59,-2.66 0.63,-3.25 1.47,-2 4.21,-2.62 1.04,-8.53 0.71,-0.35 3.97,2.13 4.6,1.03 3.03,3.31 -0.16,3.06 1.1,0.94 2.34,-1.16 0.87,-3.62 2.1,-1.47 1.19,1.03 0.65,4.25 2.16,1.56 0.72,2.29 2.22,1.34 5.37,7.47 2.63,0.34 0.15,2.03 -1.47,4.85 1.75,4.28 1.75,0.34 3.19,3.94 4.22,3.91 0.12,3.93 -0.9,2.5 1.4,2.82 -3.15,4.46 -5.69,3.41 -1.94,3.59 -1.84,1.19 -5.13,7.06 -0.53,4.94 -2.79,2.39 -1.38,0.84 -5.46,0.5 -2.1,2.09 -4.65,0.83 -1.12,2.45 -2.46,0.24 -5.38,4.42 -7.6,6.85 -1.78,4.06 -2.22,2.47 -4.05,2.78 -3.54,4.06 -3.83,3.1 -1.27,-1.49 0.93,-3.5 2.24,-0.24 1.03,-2.08 2.81,-1.53 0.54,-2.64 1.65,-4.71 -3.86,1.1 -1.93,-1.68 -3.18,-1.82 2.01,-1.12 0.25,-5.1 1.7,-1.94 4.08,-3.06 1.3,-3.89 3.59,-8.21 -2.92,-2.12 -5.07,-5.09 -3.21,-0.8 -3.57,2.04 -5.06,0.25 -3.43,2.11 -0.51,3.31 -1.47,1.48 -3.84,5.38 -0.25,5 -2.94,1.95z"/>
<path id="pLN_2" style="stroke-width:0.5" d="m845.94,336.83 2.15,-0.18 -0.54,1.43 h-1.79z"/>
</g>
<path id="pNM" :class="{ visited: visitedRegions.has('15') }" d="m420.75,295.25 2.56,-0.56 27.69,4.06 16.31,-2.44 26.44,4.44 5.75,7.06 14.37,3 12.69,4.38 12.25,-0.69 1.19,4 5.75,1.62 13.19,-9.68 16.43,-7.69 7,-1.63 2,-2.31 h3 l5.44,1.06 4.56,-1.62 21,-1.75 8.32,-4.31 7,-3.57 10.18,-14.37 7.69,-3.75 2.44,-2.94 3.94,-3.12 -0.25,-1.75 -9.94,-11.32 5.81,-15.93 10.06,-0.57 2.94,3.38 15,0.56 11.63,-10 2.87,-6.37 15.19,-1.5 9,-10.07 -0.69,-2.81 2.81,-7.19 4.69,-5.18 7.44,-0.69 2.31,-4.69 3.5,0.81 8.56,-6.18 10.32,-1.07 6.43,1.13 5.19,-1.56 2.25,-3.69 0.1,-1.5 -4.81,-7.19 -9.44,-6.19 -2.43,-4.25 -4,-0.25 -6.19,-3.75 -10.81,1.63 -4.38,8 -5.81,-3.25 -12.94,2.44 -2.44,3.62 -5.43,-3.37 -2.69,-6.25 4.06,-3.32 0.44,-8.43 2.31,-3.32 -0.69,-3.31 6.5,-22.25 4.5,2.31 12.57,2.07 3.18,-1.57 7.25,-9.37 7.19,-2.13 2.69,-4.12 -3.19,-6.313 0.81,-3.937 1.94,-3.813 5.31,-21.625 6.5,-7.75 0.44,-7.687 -2.44,-2.875 0.19,-2.75 -1.62,-1.875 -3.69,-0.375 -4.13,0.812 0.1,-4.937 3.12,-2.813 3.94,-7.687 10.62,-6.25 5.47,6.437 -1.06,3.407 -4.62,6.562 -0.32,1.688 4.91,2.281 2.72,0.375 2.06,2.562 1.63,0.219 1.71,-1.844 0.35,-3.187 1.47,-1.063 1.93,0.907 2.91,3.156 2.5,0.25 0.97,0.812 -0.38,1.844 0.13,1.938 1.78,3.437 v3.875 l3.97,5.688 3.72,2.937 3.31,0.25 1.81,-1.156 2,1.5 1.6,-0.219 1.34,-2.75 2.38,-0.437 1.62,-1.438 3.03,0.719 1.85,-1.938 3.87,-0.375 2.19,-3.812 1,-3.5 2.59,-0.531 3.41,0.875 7.34,7.687 2.44,0.5 1.38,3.094 -0.57,2.5 -2.03,2.25 v2.312 l1.34,1.532 0.16,2.312 -3.59,4.156 -0.19,4.657 -2.06,1.312 0.68,6.344 1,2.719 -0.4,2.625 3,4.626 -0.6,5.65 -0.87,0.85 -2.44,0.12 -1.44,1.03 -1.09,9.69 0.47,7.13 0.81,2.37 -0.19,2.35 -0.59,1 -2,-2.19 -1.81,-4.22 -1.44,-0.25 -1.09,0.75 -7.44,12.56 -2.59,2.38 -0.97,4.15 -8.35,7.57 -0.65,4.28 4.06,4.62 2.34,0.44 3.94,4.03 2.69,1.16 4.31,0.31 1.06,-0.63 0.85,-1.84 0.56,1.63 -1,2.78 -2,1.18 -4.28,0.35 -1,1.44 1.06,1.9 -0.84,2.69 0.72,1.87 2.28,0.47 0.1,2.19 -1.12,1.25 -2.44,0.41 -0.25,1.97 0.78,1.68 v3.41 l-0.69,1.5 -1.25,-0.1 -1.84,-1.97 -2.13,-1.16 -1.22,0.63 -0.68,1.65 -4.44,-2.65 -3.13,0.22 -0.25,3.59 -0.81,2.22 1,1.34 2.63,-0.5 1.06,0.88 1.5,3 2.72,0.84 1.31,2.16 v3.43 l-1.88,1.25 -0.46,1.79 2.21,8.84 3.66,3.06 0.94,2.22 -1.31,1.88 2.84,2.06 1.94,-0.85 8.53,-7.96 h1.15 l0.75,1.9 3.54,4.63 0.53,0.56 0.25,2.47 2.22,1.84 2.43,5.66 -0.18,0.94 -1.16,0.96 v2.38 l5.88,2.03 -0.66,5.75 -5.28,3.66 -1.41,4.37 -5.5,2.72 -2.37,-1.75 -3.38,-0.1 -0.4,1.34 1.06,2.13 -1.56,1.53 -2.07,-0.85 -3.12,0.57 -1.19,1.18 0.34,3.07 -3.03,1.93 -3.09,-1 -1.84,1.44 -4.22,5.94 -3.53,0.47 -3.91,3.44 -6.22,10.21 -0.75,-0.37 -1.5,-3.28 -3.5,-4.13 -0.25,-2 -2.69,0.1 -3.18,-2.44 -3.5,2.97 0.43,1.81 1.63,2.16 0.56,9.87 2.41,3.35 -0.32,3.06 -2.53,2.31 -1.12,-0.53 -2.25,0.25 -1.81,1.03 -8.5,-0.19 -1.25,-1.37 -0.41,-2.97 -4.19,-4.66 0.97,-1.84 -0.34,-3.34 -4.32,-3.29 -1.59,-3.9 -3.94,-4.44 -2.25,0.22 -3.65,3.34 h-2.91 l-4.12,2.97 -0.47,1.56 1.28,2.88 -0.16,4.62 -1.47,1.25 h-4.06 l-2.09,-0.87 -2.25,1.78 -0.63,1.5 -2.56,1.19 -2.47,-0.79 -1.91,0.6 -6,5.5 -1.56,2.62 -1.75,0.41 -3.31,-0.16 -1.19,-1.15 -0.19,-7.5 -2.15,-3 -4.6,0.12 -1.78,3.91 -2.5,3.62 -0.12,4.47 -1.19,1.6 -1.91,2.09 -0.56,3.47 1.56,2.37 -1.93,2.85 2.5,2.53 3.59,5.34 -2.91,4.72 -3.87,2 -3.56,2.75 -2.41,0.22 -2.97,-1.56 -2.09,0.68 -1.69,1.66 -1.25,2.25 -2.06,1.38 -5.1,-1.85 -2.09,0.94 -2.94,5.91 -2.59,7.37 -2.66,1.75 -3.93,-0.44 -1.13,1.35 -0.87,2.75 -2.22,1.75 -1.85,-0.19 -2.03,-2.78 -3.87,3.9 -1.5,2.19 -0.88,0.53 -2.47,-1.59 -4.31,1.12 -0.25,-1.53 -0.87,-0.34 -1.63,3.53 -3.94,4.16 -0.59,5.47 1.31,1.59 -0.28,2.06 -1.19,1.06 -4.12,1.04 -1.38,2.87 -2.22,1.97 -2.84,4.72 -2.75,2.34 -1.81,4 -1.81,4.75 -1.6,1.44 -4.44,0.19 -2.84,-3.78 -1.44,0.1 -1.53,1.65 -4.31,0.1 -4.75,1.12 -0.63,-4.34 -1.96,-2.91 -3.57,-1.72 -3.9,0.16 -4.66,-1.56 -2.16,-1.81 0.1,-1.19 6.75,-15.5 -3.47,-2.5 -0.22,-3.94 h-3.13 l-2.56,1.81 -2.25,0.19 -1.09,2.22 -3.47,2.44 -0.13,3.37 -3.34,5.09 0.53,10.47 -8.65,7.57 -3.29,4.96 -2.75,2.13 -4.28,0.81 -2.87,0.1 -2.38,1.78 -3.47,0.18 -5.31,-1.93 -0.56,-2.22 -3.16,-1.1 -2.53,-1.65 -0.31,-4.91 1.19,-1.5 0.72,-2.72 -0.22,-3.5 5.28,-1.59 1.9,-2 0.19,-4.69 -0.69,-2.59 2.47,-3.16 -0.59,-4.5 -5.69,-4.78 -2.03,-0.91 -6.84,0.32 -1.63,1.18 -7.34,7.44 -8.38,3.28 -11.81,0.28 -5.31,-1.53 -1.53,-1.31 -3.25,-0.53 -2.57,-1.94 -0.65,-4.5 0.94,-2.44 -0.82,-1.59 -7.47,-0.5 -2.15,-3.37 -4.97,-2.16 -3.78,-3.63 0.19,-1.34 2.28,-1.97 2.34,-3.47 6.34,-4.28 0.69,-2.75 -0.97,-4.5 -5.06,-3.34 h-16.94 l-2.68,1.12 -5.54,5.66 -3.65,0.44 -2.5,-1.78 -2.6,-3.82 -4.53,-4.31 -5.65,-12.16 0.1,-4.12 2.56,-6.59 -2.53,-4.32z">
<title>Inner Mongolia Autonomous Region</title>
</path>
<path id="pNX" :class="{ visited: visitedRegions.has('64') }" d="m540.21,409.06 1.07,-1.04 h3.66 l3.49,-0.82 3.23,-2.12 3.23,-5.24 8.43,-7.14 -0.43,-10.63 3.41,-5.2 -0.14,-3.13 2.55,-2.08 1,-0.39 1.12,-2.23 2.11,-0.36 2.62,-1.87 3.13,0.11 0.36,3.74 3.05,2.58 -0.4,2.23 -5.96,13.06 -0.14,1.76 2.41,1.83 4.37,1.51 3.88,-0.25 3.77,1.54 1.94,3.09 0.57,4.02 -0.93,0.72 -2.15,2.87 -0.94,5.1 1.26,3.01 -0.47,1.65 -2.83,0.33 -3.05,0.82 -2.48,-2.08 h-2.01 l-1.62,6.25 1.51,2.44 -0.57,1.51 -2.3,0.79 -0.47,5.38 1.37,3.84 7.32,3.34 0.61,3.09 -1.01,2.33 -0.64,3.2 -2.23,0.97 -2.55,-0.69 -1.61,0.83 -0.36,6.96 -0.86,1.22 -2.51,0.26 -2.95,-2.12 -3.87,-0.18 -2.45,-5.57 -5.88,-1.54 -2.37,-3.19 0.18,-1.98 1.94,-2.87 0.14,-4.09 -2.33,-2.8 -1.37,-4.17 -0.46,-5.42 -1.48,-1.76 -4.02,-3.12 -1.65,-3.05 -2.8,-0.14 0.25,-2.23 -1.54,-2.01z">
<title>Ningxia Autonomous Region</title>
</path>
<path id="pGS" :class="{ visited: visitedRegions.has('62') }" d="m405.21,291.55 15.31,3.99 0.17,8.65 2.31,3.96 -0.55,2.29 -2.14,4.69 0.11,4.19 2.43,5.25 3.45,6.63 4.42,4.34 2.31,3.91 2.72,1.55 3.73,-0.26 5.23,-5.38 2.74,-1.5 17.11,0.11 4.82,3.14 1.04,4.85 -0.48,2.51 -6.35,4.32 -2.89,4.06 -1.8,1.32 -0.23,1.27 3.75,3.86 5.11,1.93 1.82,3.47 7.57,0.46 1.04,1.35 -0.86,2.33 0.17,4.67 2.87,2.16 3.28,0.63 1.85,1.55 4.8,1.2 12.08,-0.31 8.12,-3.35 9.04,-8.58 7.03,-0.18 3.5,2.14 3.96,3.57 0.61,4.32 -2.34,3.22 0.74,3.2 -0.35,4.01 -1.6,2.11 -5.11,1.04 -0.55,5.46 -1.5,3.42 0.28,4.7 5.78,2.46 0.61,2.13 5.59,2.01 3.17,-0.38 0.74,-0.61 2.13,0.89 1.75,1.65 v2.33 l2.53,0.26 1.93,3.17 5.36,4.37 0.38,5.76 1.42,4.34 2.51,2.46 -0.35,4.21 -1.91,2.95 v2.05 l1.93,3.05 6.32,1.65 0.69,2.49 1.4,2.97 4.11,0.17 3.2,2.26 2.33,-0.58 0.69,-1.17 0.38,-6.62 1.77,-1.12 2.52,0.69 1.95,-0.79 0.66,-3.53 1.12,-2.08 -0.38,-2.87 -7.57,-3.68 -1.44,-3.91 0.43,-5.1 2.08,-0.84 0.96,-1.32 -1.65,-2.76 1.53,-6.02 2.21,-0.1 2.56,1.98 5.79,-0.91 0.58,2.91 1.07,1.83 2.25,0.56 0.74,0.61 6.73,1.93 3.65,3.58 2.39,-0.84 8.78,5.2 0.28,7.62 -3.22,3.02 0.25,4.69 2.03,2.8 -0.56,4.79 -1.95,1.27 -5.66,-0.28 -2.82,1.5 -3.25,-1.29 -1.06,0.23 -0.1,3.57 1.7,2.62 -11.22,2.41 -3.55,-3.12 -3,-0.33 -5.2,0.94 -0.86,2.43 0.99,2.14 -0.46,2.94 -2.79,2.64 0.15,1.4 3.83,1.42 2.06,1.72 0.23,1.76 -1.37,1.62 -3.05,6.35 1.24,1.75 -0.28,4.31 0.66,1.09 -0.5,1.04 -2.21,-0.33 -5.79,0.54 -3.1,1.62 -1.39,2.21 2.89,1.42 1.14,2.82 -0.76,3.81 -4.03,3.83 -4.09,0.1 -1.12,1.01 -0.1,4.09 -5.41,2.74 -2.81,-1.65 -1.55,0.28 -1.52,-0.97 -4.19,-0.2 -3.56,-3.83 0.1,-4.01 -1.93,-3.4 -1.14,-3.94 -1.32,0.1 -3.91,2.82 h-2.01 l-6.82,-6.12 -1.5,-4.39 -4.01,-1.19 -1.47,-3.2 0.58,-5.38 -1.37,-0.43 -1.14,-0.99 -2.19,0.3 -4.44,2.21 -4.62,1.17 -3.02,2.46 0.26,3.48 0.61,1.8 -7.54,-0.2 -2.09,-4.93 -4.41,-2.33 -7.54,-0.26 -2.23,-1.75 0.3,-6.47 2.84,-0.56 5.13,4.44 5.51,1.3 2.21,-0.64 2.18,-3.93 -0.79,-3.48 -0.1,-7.28 3.45,-1.32 4.29,-2.85 0.84,-2.2 -1.91,-2.97 1.02,-2.54 2.1,-0.89 1.83,-3.76 2.87,1.63 4.14,-6.93 0.4,-4.95 0.97,-2.79 -2.39,-2.52 -0.91,-3.91 -2.97,-1.37 -0.25,-5.07 -2.72,-2.49 -0.58,-4.88 -1.63,-2.51 -0.94,-3.83 -4.14,-3.25 -0.58,-3.1 h-1.18 l-3.52,2.25 -5.5,-2.27 -6.02,-4.01 -0.94,-2.43 -4.87,-4.47 -3.1,-1.46 -3.06,-2.9 -3.15,-1.77 -1.43,3.74 -2.78,-0.56 -8.79,-10.12 -1.93,-0.31 -3.81,-4.42 -5.99,-2.05 -2.72,2.39 -2.94,-2.36 -4.93,4.8 -3.95,-2.92 -1.87,-2.5 -12.22,-3.71 -2.27,1.94 1.51,3.97 -0.13,4.43 -3.78,5.13 -0.82,5.53 -3.58,0.58 -3.33,1.58 -4.91,-2.96 -5.92,0.36 -10.16,-3.6 -10.72,1.68 -4.1,-8.4 -6.84,0.36 -1.65,-4.01 -9.25,0.69 -2.63,-5.6 -8.39,-3.89 4.66,-3.42 1.47,-4.69 0.39,-13.24 2.13,-9.38 7.42,0.45 4.34,-3.41 1.21,-3.27 6.36,-6.56 7.23,-5.03 3.63,-4.39 7.72,-3.5 3.83,-1.3 3.56,-2.51 8.52,-1.01 5.41,-4.52 -0.94,-4.27z">
<title>Gansu Province</title>
</path>
<path id="pQH" :class="{ visited: visitedRegions.has('63') }" d="m280.84,422.12 1.16,0.1 7.56,3.65 h3.6 l4.37,-2.34 5.06,-1.09 0.75,-1.94 -0.9,-1.03 -4.72,-0.22 -1.06,-6.25 3.06,-2.78 3.31,-0.91 2.41,-1.84 -0.19,-3.97 2.5,-2.25 -0.25,-1.28 -13.97,-10.66 -0.22,-12.56 8.6,-5.53 11.93,-0.19 12.16,-1.72 6.47,-3.37 11.47,5.46 2.62,5.5 9.41,-0.59 1.69,3.91 6.71,-0.35 4.1,8.38 10.75,-1.69 10.25,3.66 6.06,-0.44 4.78,3.09 3.16,-1.5 3.9,-0.59 0.6,-5.78 3.78,-5.1 0.1,-4.37 -1.34,-4 2.19,-1.94 12.21,3.56 1.88,2.54 4.06,3.25 4.94,-5.07 2.53,2.47 2.84,-2.47 6.29,2.25 3.96,4.57 1.85,0.12 8.56,10.06 2.88,0.28 1.4,-3.46 3.1,1.62 3.46,3.19 3,1.56 4.88,4.34 0.72,2.35 5.53,3.87 1.22,-0.1 4.78,2.53 3.5,-2.25 1.31,0.16 0.28,2.62 4,3.35 1.32,3.87 1.68,2.56 0.5,4.85 2.63,2.59 0.37,5.13 2.72,1.43 1.03,3.69 2.32,2.66 -0.97,3.06 -0.35,5.13 -4.22,6.46 -2.78,-1.62 -1.5,3.69 -2.28,0.93 -1.09,2.35 1.59,3.25 -0.56,2.19 -4,2.71 -3.84,1.22 v7.19 l0.81,3.59 -1.72,4.04 -2.94,0.81 -5.37,-1.6 -4.63,-4.21 -2.78,0.15 -0.62,6.6 2.09,1.9 7.19,0.31 4.84,2.5 2.41,4.72 3.81,0.41 h3.78 l0.75,2.16 1.78,1 0.38,2.31 -1.69,3.37 -0.44,3.38 -2.19,0.4 -2.25,-2.15 -2.53,0.1 -3.59,3.5 -1.47,-0.1 -1.28,-2.53 -1.81,-2.22 h-2.22 l-5.66,3.22 -1.97,3.68 0.44,3.44 -1.69,2.97 -2.43,-0.12 -2.35,0.56 -3.84,-0.6 -1.13,-1.5 -8.34,-9.18 -1.34,-3.22 -4.04,-0.1 -4.34,3.46 -1.97,-1.5 -2.47,-0.4 -4.68,-2.94 -2.47,-0.97 -3.53,1.03 -2.47,-0.81 -4.19,0.78 -3.31,-1.12 -5.25,1.5 -4.44,2.97 -0.34,2.21 1.46,2.22 -1.25,2.35 -6.75,2.03 -0.43,2.03 0.9,1.09 0.13,3 -1.85,1.82 -0.59,3.15 -8.34,11.16 -1.38,0.81 -4.65,-2.84 -2.22,0.1 -1.94,1.59 -2.63,-0.31 -3.96,-3 -4.41,-0.94 -1.63,-6.93 -2.46,-0.69 -5.6,-4.03 -1.9,-3.66 -3.54,-1.84 -7.84,-0.6 -1.47,-0.75 -13.69,-0.37 -4.56,-2.88 -5.31,0.16 -1.47,-2.34 -2.31,-0.1 -2.69,1.47 -4.84,-1.87 -4.32,-4.54 -5.06,-2.78 -3.75,-0.31 -3.4,-1.75 -3.91,-0.84 -2.75,-1.69 -9,-0.84 -1.94,-5.94 -1.78,-3.72 -2.97,-4 -0.78,-4.78 -3.66,-4.63 -1.37,-2.87 -0.63,-2.53 0.94,-3.03 -1.47,-1.41 -0.34,-2.5 0.75,-1.91 5.16,-0.34 1.34,-3.5 -1.69,-2.31 2.38,-7.88 2.72,-4.53 0.4,-5.12 -1.09,-1.66 -4.31,-0.81 0.18,-1.63 4.97,-2.4z">
<title>Qinghai Province</title>
</path>
<path id="pXJ" :class="{ visited: visitedRegions.has('65') }" d="m286.25,133.87 -0.63,3.44 -1.81,3.31 3.31,4.69 -0.12,3.13 7.06,4.75 4.31,10 5.13,0.81 2.62,-1.69 5.69,5.88 3.38,-0.44 4.56,7.75 2,8.69 5.81,11.06 -0.81,5.06 -2.56,3.81 1.5,5.82 -6.75,9.81 -0.38,6.5 2.13,2.25 19.68,7.19 13.44,0.56 8,2.44 6.81,6.62 9.19,5.63 2.5,2.87 4.56,2 5.38,0.88 -0.94,3.75 3.56,2.43 5.38,18 6,7.32 0.94,3.12 -2.38,6.19 0.99,4.05 -5.61,4.68 -8.57,1.02 -3.5,2.43 -4.9,1.64 -6.67,3.31 -3.81,4.47 -6.89,4.77 -6.45,6.58 -1.5,3.45 -4.47,3.27 -7.33,-0.44 -2.04,9.54 -0.35,12.6 -1.41,5.13 -4.56,3.36 -3.31,-1.33 -6.06,3 -12.55,1.95 -11.97,0.31 -8.4,5.26 0.1,12.81 13.57,10.48 0.83,1.32 -2.6,2.35 0.22,3.84 -2.43,1.9 -3.23,1.11 -3.49,2.47 1.37,6.32 4.6,0.49 0.84,0.88 -0.62,1.81 -5.08,1.24 -4.11,2.03 -3.72,0.31 -7.2,-3.75 -5.83,-0.36 -6.06,0.53 -6.67,-3.97 -2.34,-0.4 -6.77,-4.2 -6.63,-1.5 -7.99,-0.58 -5.48,3.1 -10.08,-0.1 -7.07,1.23 -12.42,7.16 -1.46,0.23 -6.85,-2.21 -18.25,4.86 -2.3,-1.64 -6.14,-0.53 -6.85,-6.14 -3.94,-0.58 -2.51,-1.72 -5.71,0.22 -2.51,-2.21 -2.44,0.13 -4.5,1.99 -4.64,6.85 -5.48,0.8 -2.96,-4.38 -4.78,-1.85 -2.56,0.93 -8.49,-3.98 -2.82,-2.92 -3.32,5.17 -3.84,2.79 v2.87 l-3.05,0.57 0.62,4.86 -4.818,5.4 -5.171,-2.39 -3.138,0.62 -2.474,-0.75 -3.403,0.62 -2.077,-1.33 -2.873,-3.8 -4.817,-2.3 -1.017,-2.03 -0.09,-3.76 -0.796,-2.25 0.31,-2.96 -1.282,-4.82 2.431,-5.48 -3.536,0.88 -11.755,-4.59 -7.292,-5.44 -2.299,-3.76 -5.082,-1.37 -2.917,-7.07 1.503,-3.58 -0.398,-9.06 -2.43,-2.82 -3.492,-0.31 -0.84,-4.38 -3.977,-2.65 -3.491,-0.27 -6.232,-3.58 -0.353,-3.75 11.888,0.1 0.663,-2.61 -1.503,-3.54 1.768,-9.19 -1.193,-4.51 2.342,-4.46 0.133,-1.99 -6.983,-5.35 -4.994,-0.92 -2.475,2.07 -2.121,-4.28 0.751,-4.6 2.519,-1.81 -1.944,-5.48 1.502,-4.86 4.508,-0.45 1.547,-2.91 -0.486,-3.41 1.414,-3 4.287,-2.21 4.861,1.06 2.696,-1.55 5.701,-0.92 1.282,-3.54 6.187,3 6.01,-2.12 1.061,3.45 v3.67 l2.298,1.06 3.491,-1.41 4.42,1.63 4.331,-2.65 7.424,-9.06 3.492,0.18 7.027,2.96 6.938,0.26 2.784,1.24 8.8,-7.2 13.56,-4.25 4.69,-0.13 5.7,-1.86 2.21,-1.14 3.8,0.7 1.68,-0.97 1.68,-8.97 -0.22,-3.01 2.69,-3.62 3.94,-0.84 -0.71,-3.4 6.5,-2.12 -0.1,-1.95 -0.93,-1.94 1.41,-4.33 -2.96,-13.84 1.06,-1.81 0.62,-7.03 2.83,-4.15 -3.09,-2.7 -3.67,-0.61 -0.97,-1.51 3.36,-2.52 15.33,-0.7 10.52,-1.33 3.49,4.95 5.57,-0.31 2.87,2.34 2.65,-0.92 1.24,-4.87 -4.11,-3.75 4.73,-9.55 0.93,-2.87 10.03,-16.18 2.21,-5.87 3.14,0.79 8.97,6.54 11,1.28 2.74,4.25 0.98,-0.1 5.03,-2.57 5.44,-0.57 3.67,-4.38 -1.73,-5.52 1.2,-9.5 4.73,-10.17 6.63,1.02 7.6,-3.09 2.3,-4.47 0.48,-5.17 6.67,-1.41 4.16,2.3 2.56,-1.33z">
<title>Xinjiang Autonomous Region</title>
</path>
<path id="pXJd" style="stroke:none" :class="{ visited: visitedRegions.has('65') }" d="m70.291,403.06 2.497,-2.32 5.171,-1.96 0.906,-0.64 4.132,-0.75 0.95,-1.18 1.348,-0.81 2.541,2.03 3.469,-0.6 2.254,0.33 2.519,-0.37 0.928,2.96 0.994,0.66 2.52,-0.1 -0.8,2.57 0.53,1.79 1.84,0.93 0.22,1.7 0.77,0.48 2.12,-0.55 0.1,3.03 0.16,1.19 0.92,0.66 2.21,-2.25 1.06,-0.29 0.53,1.26 -3.62,5.04 -3.62,2.92 -0.25,2.91 -2.96,0.47 0.67,4.82 -4.807,5.56 -5.125,-2.31 -3.313,0.56 -2,-0.94 -3.437,0.57 -2.688,-1.57 -2.187,-3 -5.188,-2.93 -1.062,-1.88 0.06,-2.37 -0.5,-6.44 -1.312,-5.06z">
<title>Xinjiang Autonomous Region</title>
</path>
<path id="pXZ" :class="{ visited: visitedRegions.has('54') }" d="m95.415,432.67 4.905,-5.43 -0.75,-4.95 3.14,-0.66 0.17,-2.61 3.8,-3.23 2.57,-3.89 0.35,-1.15 3.36,3.01 8.31,4.11 2.96,-0.88 4.55,1.72 2.7,4.37 5.39,-0.84 4.33,-6.45 5.13,-2.21 h2.21 l2.87,2.08 5.26,-0.18 2.69,1.64 4.03,0.57 6.67,5.88 6.32,0.75 2.25,1.5 15.56,-3.66 2.39,-1.02 7.33,2.12 1.86,-0.44 11.53,-6.98 6.76,-1.2 10.66,0.18 5.12,-2.96 7.78,0.35 7.07,1.64 6.76,4.06 2.48,0.58 6.49,3.89 6.1,-0.67 3.98,0.4 -0.35,3.67 -4.86,2.12 -0.14,1.77 4.25,0.97 1.06,1.46 -0.14,5.08 -2.74,4.24 -2.52,8.09 1.64,2.34 -1.15,3.54 -5.04,0.44 -1.15,1.55 0.62,3 1.42,1.24 -1.24,3.58 0.66,1.99 3.27,5.3 2.08,2.35 0.66,4.46 3.54,4.9 3.09,9.02 8.97,0.84 2.79,1.72 3.75,0.71 3.23,1.72 4.29,0.4 4.59,2.52 4.6,5 4.99,1.63 2.74,-1.41 2.48,0.17 1.28,2.26 5.08,0.1 5,2.74 13.17,0.22 1.72,0.88 7.82,0.57 3.49,1.77 1.95,3.54 5.17,3.84 2.83,1.06 1.54,6.9 4.03,0.88 4.15,2.92 2.65,0.44 2.39,-1.81 2.07,0.22 4.56,2.7 1.41,-0.67 8.4,-11.49 0.35,-2.65 2.03,-1.94 -0.1,-3.05 -0.93,-1.29 0.44,-2.12 3.71,-0.92 2.87,3.35 3.14,2.17 5.26,1.41 4.2,3.14 0.49,3.8 2.74,3.18 0.39,6.1 2.92,3.94 4.46,4.42 -0.31,1.54 -2.38,1.77 -1.73,0.13 0.36,2.35 2.52,3 1.06,4.51 1.59,1.5 0.35,12.99 1.06,2.79 -0.22,4.06 -0.62,1.11 1.02,11.71 -1.9,-0.13 -1.68,1.37 -0.26,3.22 -1.99,2.43 -2.88,0.89 0.53,3.49 -1.28,2.65 0.67,1.42 -0.14,5.52 -3.58,1.68 -2.78,-1.86 -4.2,3.54 -1.9,-2.87 -3.01,-0.58 -2.38,-3.49 -2.56,-0.49 -5.66,5.66 -3.71,-3.67 -2.61,1.06 -2.08,-1.01 -2.12,0.13 -3.31,-2.43 -3.98,1.55 -1.73,-1.2 1.6,-3.27 4.55,-3.58 -0.14,-1.46 -2.6,-4.86 -2.7,0.8 -2.38,2.12 -0.84,-3.98 3.58,-1.59 1.14,-2.21 -3.27,-0.88 -2.21,-3.45 -9.5,3.8 -1.9,3.49 -1.63,0.84 -3.14,-0.57 -4.16,-2.26 -4.37,-1.37 -2.08,-3.31 -2.3,1.72 -2.96,1.15 -5.21,3.85 -2.43,0.39 0.13,1.99 -7.2,3.76 -7.03,-0.27 -2.3,0.93 -1.5,4.42 -4.42,2.92 -4.82,3.18 -0.17,3.23 -4.69,1.85 -6.94,0.1 -1.72,0.97 -2.61,-0.17 -8.7,-4.11 -3.41,-2.83 -7.51,-0.13 -4.64,-1.37 -4.69,-5.88 -6.67,-2.04 -10.43,4.34 -6.89,5.96 -4.02,5.53 -2.97,1.68 -2.07,-3.5 3.31,-6.93 -0.62,-3.41 -2.91,-2.74 -2.79,0.4 -7.91,2.34 -9.32,1.55 -3.8,-2.3 -3.89,1.46 -10.79,-8.84 -4.86,2.79 -2.56,-0.31 -2.43,-3.94 -4.16,2.61 -1.54,-4.33 -6.1,-4.99 -5.88,-0.76 -1.46,-4.95 1.46,-1.94 -1.1,-1.46 -4.6,1.11 -5.22,-4.16 -7.24,-3.31 0.79,-6.59 -1.06,-4.37 -2.52,-1.11 -3.4,4.47 -1.99,0.44 -4.24,-4.91 -0.44,-5.7 -6.15,-6.5 -2.25,-1.06 -3.71,-5.83 -4.42,-1.81 -3.49,-4.11 -6.5,-3.36 -0.88,-3.89 -10.88,7.07 -1.59,-5.21 -3.135,-2.17 -2.121,-3.58 -7.292,-6.14 1.812,-1.77 -1.282,-1.46 -1.989,-0.48 -3.182,-4.42 -3.314,-1.33 -3.669,-0.22 -3.535,-4.64 -2.166,-7.91 -5.656,1.63 -0.663,-3.66 1.767,-3.36 -0.883,-3.14 1.988,-5.61 -3.8,-6.85 0.751,-2.12 -0.221,-2.44 1.061,-1.72 4.817,0.13 0.309,3.63 2.563,2.47 5.304,-1.59 3.977,-0.84 2.652,-3.84 -1.591,-4.6 1.149,-3.53 -5.745,-4.69 -1.37,-3.45 -0.631,-1.77 1.326,-5.05 v-3.02 l-0.379,-3.91 0.379,-1.39 1.326,-0.44 2.651,-0.38 1.515,-1.33 0.379,-1.83 -0.568,-1.58 3.337,-0.68 2.232,0.77 3.071,-0.44 2.707,1.245z">
<title>Tibet Autonomous Region</title>
</path>
<g id="pXZd" style="stroke:none" :class="{ visited: visitedRegions.has('54') }">
<title>Tibet Autonomous Region</title>
<path id="pXZd1" d="m102.99,421.85 v-2.86 l3.68,-2.7 3.35,-5.13 1.69,1.63 -0.73,0.88 -1.65,3.67 -1.43,1.04 -1.87,5 -3.52,4.93 -1.98,-0.8 -0.64,-4.97z"/>
<path id="pXZd2" d="m75.188,449.96 -0.631,-1.77 1.826,-5.05 v-1.52 l-0.379,-3.91 0.379,-1.39 1.326,-0.44 2.651,-0.38 1.515,-1.33 0.379,-1.83 -0.568,-1.58 3.337,-0.68 2.232,0.77 3.071,-0.44 2.707,1.245 -0.309,4.38 -0.486,1.23 -0.708,-0.13 -0.132,1.64 -0.663,0.7 -1.679,1.11 -4.641,-1.15 -1.414,0.44 -1.724,-0.88 -1.458,0.62 -0.177,1.5 0.04,2.34 0.973,1.55 -0.221,2.34 -2.298,-0.22 -0.486,1.9 -0.663,2.56z"/>
</g>
<path id="pSC" :class="{ visited: visitedRegions.has('51') }" d="m410.78,511.47 2.34,-0.6 1,-2.59 -1.31,-2.12 0.41,-1.97 4.81,-3.5 4.91,-1.19 2.9,1.03 4.6,-0.75 2.5,0.78 4.25,-0.87 6.62,3.75 2.03,0.47 1.97,1.4 4.53,-3.34 h3.97 l1.44,3.31 10.06,10.72 3.47,0.62 2,-0.78 2.25,0.56 2.03,-3.25 -0.22,-3.56 1.82,-3.44 5.53,-3.43 2.4,0.37 1.75,1.97 1.22,2.5 h1.1 l3.96,-3.41 h2.75 l1.91,2.07 2.13,-0.35 0.53,-3.15 1.9,-3.35 -0.47,-2.47 -2.06,-1.5 -1.59,-4.81 -0.22,-2.59 3.03,-2.31 4.72,-1.25 4.34,-2.44 1.88,-0.28 2.9,1.56 -0.46,5.06 1.56,3.47 4.03,1.22 1.47,4.41 6.75,5.93 2.22,0.28 3.56,-3.03 h1.31 l2.19,5.35 1.06,1.87 -0.15,3.97 3.65,3.94 4.31,0.4 1.5,1.04 1.1,-0.66 2.9,1.72 5.44,-2.69 0.22,-3.97 1.38,-1.25 9.25,0.38 1.56,1.06 0.5,3.16 2.09,1.15 8.66,-1.94 2.25,-1.03 4.34,0.25 1.38,4.07 1.28,1.18 2.15,0.1 1.66,-1.25 2.34,2.31 2.94,0.5 5.16,4.03 h0.94 l4.9,-2.28 3.91,-0.34 3.06,1.87 -0.12,1.19 0.37,2.06 -2.37,2.81 0.1,1.13 3.94,2.62 0.1,0.85 -0.5,2.09 -2.72,1.81 -2.22,3 -5.22,12.13 -1.93,1.5 -5.16,-0.38 -1.69,1.03 -1.12,6.72 -6.22,9.38 -2.38,0.69 -4.37,-0.91 -4.44,-5.34 -1.16,0.56 -1.75,1.5 -2.28,0.15 -4.59,-2.84 -2.63,-1.03 -2.37,0.66 -2.88,5 2.91,3.84 -0.16,1.22 -0.68,0.75 -9.03,7.4 5,6.29 3.37,0.53 2.25,6.37 7.13,1.19 2.25,2.5 0.9,3.66 -0.4,2.68 -6.19,-4.81 -1.28,0.53 -0.69,2.66 -2.69,0.28 -1.59,2.22 0.4,3.84 7.13,3.03 2.87,0.63 1.29,3.44 1.9,3.18 -1.06,1.57 h-4 l-7.13,2.66 -2.9,-2.19 -4.69,0.69 -1.22,-1.19 0.38,-3.84 -1.1,-0.22 -2.06,-2.16 -2.12,0.38 -2.07,4.12 -4.65,0.91 -3.35,-0.62 -2.53,-2.35 1.19,-1.65 -0.31,-3.69 -2.41,-1.66 -0.69,-4 1.53,-1.75 -1.78,-1.81 -3.68,1.44 -3.6,-0.75 -1.72,2.84 1.5,3.72 -1.22,1.66 -5.03,0.87 -1.4,3.94 1.22,2.03 -0.88,4.19 -4.84,4.56 -2.72,3.25 -1.85,0.22 -1.21,1.37 -0.85,10.19 2.88,4.16 -0.38,6.31 -0.28,1 -6.37,3.69 -1.57,-3 -2.03,0.28 -6.75,4.15 -0.87,1.54 -6.13,-0.22 -1.72,-2.69 -2.37,-0.66 -0.38,-5.47 -2.72,-1.9 0.66,-3.66 -1.16,-0.75 -1.28,-2.69 -2.31,-1.81 -0.5,-5.72 -4.72,-4.62 -0.5,-3.44 -6.06,-6.87 -3.06,-0.1 -6.19,-2.15 -0.56,-3.66 -1.35,-3.09 1.75,-2.6 v-2.84 l-2,-1.06 -2.71,0.56 -5.82,5.69 -1.78,-0.32 -2.56,2.53 -3.41,-4.71 -2.47,-31.16 0.66,-1.72 v-3.72 l-0.94,-2.34 -0.34,-13.25 -1.81,-1.35 -0.97,-4.5 -2.35,-2.84 -0.37,-2.34 1.53,-0.19 2.63,-1.88 0.1,-1.46 -4.31,-4.13 -2.85,-4.56 -0.43,-5.78 -2.72,-3.07 -0.5,-3.81 -4.28,-3.34 -5.32,-1.25 -3.25,-2.31z">
<title>Sichuan Province</title>
</path>
<path id="pCQ" :class="{ visited: visitedRegions.has('50') }" d="m579.61,606.9 1.68,-0.97 1.08,-2.37 -0.32,-2.55 2.19,1.94 -0.22,2.55 2.77,1.54 1.79,-1.79 1.37,-3.99 1.54,-2.69 2.91,-1.26 2.8,1.3 2.15,-0.22 2.58,-2.01 -1.61,-4.09 0.72,-2.51 1.11,-0.15 2.66,1.44 2.01,0.32 1.07,2.48 1.62,0.64 2.33,-1.93 5.1,0.1 1.94,5.21 -0.61,2.33 1.54,1.15 3.59,0.93 0.22,3.77 0.79,2.37 1.25,-1.15 -0.46,-1.9 0.75,-0.32 1.29,1.33 -0.29,2.33 1.58,1.44 4.02,0.21 1.94,-2.66 v-2.19 l1.83,-1.18 -0.9,-13.64 -2.8,-1.26 -4.27,-5.17 -0.36,-4.63 -2.62,-0.79 -3.27,-3.59 -2.19,1.76 1.08,-10.3 -3.05,-4.2 4.13,-3.02 2.91,0.1 4.16,-1.83 4.31,0.28 4.84,-1.58 5.75,-6.28 3.8,1.51 1.47,-3.09 -0.68,-3.95 1.01,-2.26 -0.79,-3.55 -2.37,-2.91 -2.16,-1.44 -0.1,-4.48 -5.71,-0.18 -6.93,1.25 -1.61,-0.39 -0.83,-3.2 -5.03,-0.53 -4.73,-3.09 -0.65,0.54 0.57,2.37 -2.54,3.01 0.21,0.94 3.84,2.87 0.4,0.93 -0.76,1.8 -2.87,1.93 -2.22,3.31 -4.89,11.38 -2.22,1.72 -5.17,-0.25 -1.62,0.82 -1,6.97 -6.53,9.22 -2.3,0.86 -4.35,-1.14 -4.05,-5.14 -1.33,0.43 -2.08,1.65 h-1.83 l-5.03,-3.15 -2.76,-0.72 -2.16,0.93 -2.4,3.95 v1.36 l2.33,2.52 0.36,1.61 -1.18,1.4 -8.37,6.68 v0.9 l4.49,5.95 3.19,0.29 1.22,1.87 1.33,4.77 7.15,1.08 2.33,2.44 0.86,3.84 -0.25,2.73z">
<title>Chongqing Municipality</title>
</path>
<path id="pGZ" :class="{ visited: visitedRegions.has('52') }" d="m579.45,606.45 0.54,0.11 1.65,-0.72 1.18,-2.26 -0.64,-3.09 2.4,2.08 -0.36,2.84 2.55,1.38 2.3,-1.83 1.02,-4.22 1.64,-2.44 2.83,-1.19 3.04,1.49 2.11,-0.37 2.25,-1.94 -1.33,-4.27 0.82,-2.46 1.24,0.12 2.19,1.28 2.07,0.34 1.24,2.58 1.49,0.49 2.31,-1.89 5.01,0.17 1.69,3.28 0.28,1.96 -0.32,2.19 1.51,1.11 3.48,0.75 v3.95 l1.02,2.3 1.25,-1.06 -0.46,-2.01 h0.72 l1.49,1.18 -0.44,2.41 1.85,1.36 3.75,0.1 1.67,-2.53 0.27,-2.46 1.87,-0.68 1.02,2.68 1.6,1.81 -0.48,2.31 0.35,4.63 0.72,3.68 2.03,2.36 -0.43,2.35 -1.53,1.22 -1.11,1.9 -3,1.27 -5.81,5.69 1.2,2 1.38,0.35 3.2,-2.31 2.31,-0.16 1.8,-0.81 1.92,0.16 1.6,1.44 0.66,4.81 -0.54,1.18 -3,2.5 2.09,2.78 -0.47,1.88 -1.4,1.94 v2.08 l3.17,4.42 0.45,2.01 -3.97,5.96 -3.14,-0.99 -2.51,1.17 v1.29 l1.42,1.29 -0.58,1.82 -4.45,0.18 -1.59,0.91 v0 l-1.51,3.61 -4.65,-2.77 -2.76,1.3 -1.73,2.08 -1.18,3.86 -2.95,0.37 -1.75,1.48 -4.4,-3.49 -2.77,0.63 -2.45,-1.9 -0.94,-2.94 -1.24,-0.74 -4.25,3.88 -1.45,2.96 -1.73,1.56 -3.86,0.36 -7.34,4.72 -2.6,0.74 -0.1,3.85 -4.15,2.75 -1.25,-1.22 -2.34,-0.1 -1.36,-1.11 -4.76,-0.47 -1.36,-2.82 -5.57,-0.66 -1.27,0.77 -1.81,3.16 -2.21,0.66 -2.41,2.12 -2.9,-0.12 -2.07,-0.92 0.74,-2.51 2.33,-3.34 0.49,-5.49 -2.28,-2.98 -3.39,-1.47 -2.61,-5.84 3.72,-7.66 0.25,-4.9 2.94,-3.41 -5.11,-6.32 -1.74,1.08 h-3.86 l-1.87,2.5 -1.52,0.16 -3.79,-0.7 v-3.12 l-1.33,-2.3 1.24,-2.66 -0.5,-1.81 -2.96,-1.33 5.54,-6.8 2.05,-0.25 3.46,1.86 3,-2.72 3.7,1.68 h7.32 l2.25,-1.04 2.87,-0.56 3.25,-8.13 4.59,-0.7 3.16,1.94 7.16,-2.37 3.7,-0.1 1.2,-1.42 -2.35,-3.89 -0.92,-3 -3.23,-0.61 -6.62,-2.89 -0.61,-3.73 1.6,-2.08 2.6,-0.58 0.75,-2.37 1.64,-0.55z">
<title>Guizhou Province</title>
</path>
<path id="pYN" :class="{ visited: visitedRegions.has('53') }" d="m420.16,614.72 3.78,-3.41 2.68,1.63 3.69,-1.6 0.31,-5.12 -0.78,-1.85 1.13,-2.75 -0.5,-3.56 3.06,-0.4 1.91,-2.54 0.18,-3.03 1.63,-1.59 h1.97 l1.47,19.25 3.43,4.97 2.63,-2.6 2.03,0.29 5.53,-5.69 2.85,-0.56 1.75,0.9 0.21,3.13 -1.59,2.34 1.28,3.25 0.38,3.47 6.28,2.44 h3.15 l5.88,6.84 0.59,3.38 4.57,4.68 0.53,5.63 2.47,2.03 1.21,2.59 1.1,0.44 -0.63,3.94 2.53,1.84 0.6,5.35 2.53,1.06 1.44,2.28 5.84,0.41 1.47,-1.66 6.69,-4 1.65,-0.22 1.66,3 6.47,-3.91 0.59,-2.09 v-5 l-2.69,-4.12 0.85,-10.19 1.28,-1.72 1.81,-0.19 7.56,-7.65 0.72,-4.16 -1.15,-2.19 1.65,-3.65 4.81,-0.89 1.19,-1.66 -1.42,-4.02 1.58,-2.57 3.64,0.68 3.81,-1.33 1.75,1.72 -1.5,1.55 0.55,4.02 2.44,1.64 0.2,3.81 -1.2,1.7 3.11,2.53 3.4,0.41 4.17,-0.95 1.97,-3.8 2.22,-0.63 2.09,2.21 0.86,0.25 -0.26,3.78 1.34,1.22 -3.15,8.19 -3.18,0.29 -2.18,1.44 -2.85,-0.39 -4.33,0.26 -1.82,-1.34 -2.28,-0.34 -2.71,2.84 -3.4,-2.26 h-1.27 l-6.05,6.34 v1.05 l2.8,1.04 0.69,1.75 -1.56,2.88 1.53,2.2 0.2,3.13 3.69,0.93 1.68,-0.68 1.22,-1.94 3.96,-0.23 1.82,-1.19 5.3,6.31 -2.8,3.38 -0.26,4.89 -3.97,7.82 2.66,5.74 3.42,1.48 2.05,3.03 -0.47,5.86 -2.18,2.77 -1.37,5.37 2.55,4.58 1.25,0.85 0.89,-2 3.22,-0.13 1.28,0.72 1.79,-1.05 2.85,2.32 0.67,4.71 5.27,2.02 2.71,-2.33 2.75,1.88 2.14,0.67 2.6,-0.85 1.3,-0.57 3.87,4.32 -1.41,8.55 -2.04,0.49 -2.63,-0.58 -7.4,7.47 -4.32,-1.88 -8.82,6.16 0.15,4.62 -10.73,3.83 -2.57,-2.62 -2.82,2.45 -2.19,5.23 -6.45,-6.5 -2.44,4.52 -3.33,-4.38 -7.69,7.64 -8.78,-6.81 -2.44,0.66 -1.15,2.76 -5.03,4.43 -9.66,-1.08 -2.92,5.67 4.01,7.7 0.89,8.32 -1.07,7.42 -2.68,-1.28 -6.84,0.12 -3.75,-11.73 -6.14,2.22 -4.72,3.96 -4.22,-1.61 -3.47,2.07 -2.29,-5.71 -2.69,-2.21 0.25,-6.25 -16.06,-3.08 1.56,-5.42 2.55,-3.54 -0.39,-5.15 3.46,-3.78 -0.68,-3.72 -8.28,-0.1 -3.38,-2.91 -1.08,-8.19 -2.62,-7.3 2.65,-4.48 -4.95,0.19 -6.2,-1.42 -6.17,1.17 -4.52,4.22 -3.03,0.28 v-2.61 l2.3,-4.66 -0.72,-3.98 -1.55,-1.56 -0.85,-4.55 1.23,-3.22 3.62,-1.19 -0.79,-2.4 2.48,-6.43 5.36,-1.36 1.89,-4.79 3.16,-0.36 3.36,-4.78 2.42,-0.66 1.23,-1.67 -1.75,-3.69 2.74,-3.97 1.55,-15.5 -1.4,-5.98 0.86,-3.53 -0.2,-4.24 -4.17,-2.7 -2.52,2.87 -4.14,-9.23z">
<title>Yunnan Province</title>
</path>
<path id="pBJ" :class="{ visited: visitedRegions.has('11') }" d="m736.53,323.36 -1.15,-4.09 2.09,0.72 v-1.15 l1.65,-2.73 2.58,-0.71 5.82,5.45 2.15,0.61 1.4,-1.33 0.97,0.54 2.8,-0.5 0.83,1.72 -2.01,1.87 -0.54,2.48 0.93,2.19 2.59,2.47 -2.7,3.74 -2.44,0.14 -1.4,0.86 -1.83,0.15 -2.26,1.68 1.47,1.83 2.41,1.91 0.28,2.15 -1.79,2.12 -4.2,0.43 -1.36,1.36 -0.36,1.69 -1.48,0.39 -3.33,-1.72 -7.47,1.72 -4.06,-2.65 -1.76,-3.23 1.08,-5.06 1.83,-2.77 2.98,-1.11 0.5,-3.05 -1.79,-2.26 0.65,-2.19 2.8,-2.19 1,-1.01z">
<title>Beijing Municipality</title>
</path>
<path id="pTJ" :class="{ visited: visitedRegions.has('12') }" d="m753.8,343.78 0.36,-3.69 -0.22,-5.39 2.3,-3.48 2.19,-0.36 2.8,1.22 -0.18,3.05 -1.08,1.08 0.54,3.52 2.37,3.19 2.05,-0.21 1.22,1.11 0.61,2.69 2.47,0.4 1.3,1.47 -0.29,4.4 -0.95,0.22 -4.14,2.85 -1.81,4.41 0.42,5.56 -2.62,0.95 -5.69,-2.27 -2.3,0.86 -1.97,-0.4 -2.66,-3.09 -0.29,-1.93 1.48,-3.31 -0.1,-2.8 -1.22,-2.08 0.65,-3.87 -0.54,-2.45 1.65,-1.83z">
<title>Tianjin Municipality</title>
</path>
<g id="pHE" :class="{ visited: visitedRegions.has('13') }">
<title>Hebei Province</title>
<path id="pHE_1" d="m798.72,329.16 -2.22,-1.16 -0.72,-3.16 -2.75,-1.9 -1.25,-4.1 -5.34,-0.59 -1.53,-2.16 -3,0.22 -3.44,-3.78 2.12,-2.12 -0.28,-2.75 2.47,-2.69 v-1.72 l-1.03,-0.53 -2.63,0.1 -1.62,0.88 -8.66,-0.13 -1.15,-1.09 -0.32,-3.03 -4.22,-4.75 0.94,-2.13 -0.53,-2.94 -4.12,-3.34 -1.88,-4.12 -3.78,-4.35 -2.53,0.38 -3.28,2.9 -2.78,0.16 -4.54,3.25 -0.12,1.62 1.25,2.79 -0.13,4.28 -1.15,1.25 -4.35,0.1 -2.28,-0.81 -4.31,4.22 -1.41,0.43 -2.5,-1.03 -6.18,4.72 -3,4.06 -4.91,0.5 -1.19,-1.5 -0.25,-7.12 -2.09,-3.25 -4.31,0.1 -2.44,4.88 -2.13,2.65 -0.15,4.81 -3.22,3.32 -0.56,3.62 1.65,1.97 -1.75,2.91 0.47,1.28 1.75,1.28 6.1,9 0.62,3.31 2.41,1.03 0.15,1.07 -2.62,1.81 -2.83,0.91 -1.17,2.61 1.02,2.03 1.94,1.06 3.03,0.29 0.97,1.17 0.64,3.2 2.01,1.9 0.84,2.19 -1.13,3.2 -0.48,4.69 -2.5,1.63 -5.48,1.18 -2.16,2.56 0.24,1.88 1.3,1.23 -0.17,1.18 -4.14,4.42 0.36,6.14 1.9,1.48 3.2,1.39 1.19,3.25 5.68,7.53 -3.38,7.23 -0.48,3.14 -1.09,1.1 0.2,2.54 0.62,1.99 -2.52,3.76 -2.19,0.4 v3.11 l2.98,4.16 2.34,1.1 5.24,0.44 1.33,0.98 5.94,0.33 1.88,1.52 1.94,0.22 1.81,-1.39 1.35,-0.22 2.68,1.72 2.54,-2.27 2.25,-0.1 3.65,1.28 0.22,-2.36 -3.6,-5.19 0.17,-4 2.72,-3.63 2.17,-1.5 2.82,-6.32 1.57,-5.88 2.99,-1.08 0.99,-3.78 1.42,-1.68 1.83,0.98 1.39,-0.87 2.79,-3.91 1.56,-2.41 2.17,-0.73 3.93,-0.5 2.83,0.22 1.75,-1.04 v-2.61 l2.69,-2.63 1.73,-2.4 -2.81,-2.28 -2.83,-5.38 -0.1,-0.92 -2.45,0.75 -6.16,-2.41 -1.86,1.06 -2.3,-0.64 -2.47,-2.69 -0.24,-2.59 1.19,-2.87 0.1,-2.85 -1.2,-1.84 0.71,-4.28 -0.73,-2.26 -3.87,0.4 -1.79,1.53 -0.11,1.74 h-2.3 l-2.63,-1.32 -7.42,1.48 -4.02,-2.54 -1.53,-3.25 0.6,-4.38 1.86,-3.29 3.09,-1.17 0.82,-3.23 -2.19,-2.34 0.91,-2.21 2.78,-2.1 0.97,-0.82 3.05,-0.61 -0.95,-3.83 1.73,0.25 0.15,-1.17 1.88,-2.72 2.5,-0.44 5.81,5.34 1.94,0.58 1.81,-1.22 0.89,0.62 2.45,-0.55 0.95,1.74 -2.12,1.84 -0.53,2.19 1.02,2.43 2.89,2.58 h1.77 l2.54,1 0.11,3.42 -1.55,0.69 0.64,3.95 2.24,2.66 2.47,0.3 0.93,0.91 0.68,2.72 2.79,0.46 0.79,1 v4.67 l1.34,-0.29 3.52,1.74 2.37,-1.19 1.54,-1.8 h3.59 l1.55,-1.04 1.1,0.44 0.72,-4.76 1.27,-4.6 2.83,-4.62 2.46,-1.48 v-2.25z"/>
<path id="pHE_2" d="m746.11,337.22 2.59,-1.63 1.69,-0.17 1.14,-0.5 2.06,-0.26 0.71,5.61 -0.58,3.62 -3.39,-0.41 -0.39,-2.39z"/>
</g>
<path id="pHA" :class="{ visited: visitedRegions.has('43') }" d="m647.06,467.43 5.6,0.5 2.87,-1.18 2.45,-2.82 2.74,-0.72 1.8,-1.45 4.45,-0.45 5.01,-5.4 2.02,-1.21 h2.57 l1.06,-2.93 2.3,-1.09 5.6,0.37 2.01,-2.08 3.51,0.65 3.56,-2.1 5.01,-3.56 3.69,-3.08 0.31,-8.37 0.64,-2.4 v-6.55 h5.6 l1.65,1.23 5.56,0.38 1.91,1.31 2.15,0.23 1.81,-1.43 1.6,0.29 2.41,1.25 2.62,-2.3 1.93,-0.18 1.46,0.88 2.64,0.44 v0.96 l-1.29,1.39 -0.74,3.1 1.1,0.77 5.6,-4.18 2.81,-1.09 2.95,-2.23 0.32,1.98 -3.66,2.87 -8.15,8.52 -0.88,2.44 -2.24,1.51 -1.76,1.96 -0.49,2.17 -1.83,2.03 v1.74 l1.08,0.68 4.74,0.43 3.1,2.5 2.61,1.23 0.3,2.66 2.28,1.8 3.03,-1.49 3.95,0.12 1.4,-0.93 2.39,0.52 0.54,2.12 4.14,3.37 2.59,0.29 0.88,0.88 0.59,3.46 1.78,2.08 -0.76,1.46 -1.31,0.89 -1.24,1.73 -3.5,2.26 h-1.56 l-3.03,-4.06 -2.24,-1.9 -2.86,-0.22 -1.65,1.26 -0.65,2.89 1.49,6.62 -4.02,1.88 -1.07,3.27 0.98,2.32 -1.25,3.34 -2.12,1.47 -3.7,-0.38 -0.45,1.87 0.6,1.29 4.38,1.09 1.29,1.31 0.18,3.2 1,1.69 3.2,0.5 2.99,2.65 1.91,0.31 1.9,-2.35 2.23,-1.24 -0.11,2.33 2.4,7.15 -1,7 -3.93,1.04 -2.89,3.21 -0.54,5.56 -2.96,-0.78 -0.61,-2.07 -1.87,-0.77 -1.06,0.95 -0.45,1.63 -4.61,0.54 -4.67,-2.12 -0.46,-2.67 -1.67,-0.16 -1.55,0.39 -2.71,-1.81 h-0.93 l-1.72,1.61 h-1.74 l-1.51,-1.76 -2.64,-2.14 -0.84,-2.71 -0.56,-6.21 -0.93,-0.7 -1.6,0.63 -1.94,1.92 -2.19,0.84 -4.38,-2.31 -2.85,0.21 -6.07,2.43 -2.39,-0.95 -4.32,1.34 -10.2,-2.55 -1.86,-1.99 -3.74,-0.38 -2.27,-3.21 -3.58,-2.73 -2.85,-4.72 -2.5,-2.51 0.11,-5.46 -3.52,-3.01 -1.41,-3 -2.8,-1.76 0.25,-2.46 -0.83,-3.73 -2.74,-1.13 -0.49,-2.57 -1.87,-1.67 -0.53,-2.72z">
<title>Hunan Province</title>
</path>
<path id="pSD" :class="{ visited: visitedRegions.has('37') }" d="m769.48,374.61 -1.59,2.53 -2.61,1.92 -0.36,3.41 -1.8,0.89 -2.48,-0.22 -6.41,1.14 -1.43,2.91 -4.14,4.47 -1.89,-1.11 -1.25,1.89 -0.96,3.59 -3.09,1.06 -2.2,7.66 -2.46,4.84 -2.54,1.8 -2.16,2.97 -0.24,3.51 1.6,3.1 2,2.44 0.19,3.14 -1.64,1.98 -0.27,2.75 0.8,0.83 5.7,-4.17 3,-1.32 2.81,-2.14 0.39,1.77 -4.64,3.84 -7.47,7.94 -0.5,2.28 -4.09,3.06 -0.5,2.47 -1.94,2.08 -0.14,1.92 5.74,1.19 3.67,2.44 2.09,0.9 0.39,2.82 2.52,1.68 3.14,-1.28 3.65,-0.2 1.63,-0.72 3.39,0.28 2.92,-1.61 0.67,-5.95 5.3,-2.22 2.52,0.88 3.84,3.93 1.34,3.43 1.39,0.96 2.68,-1.78 2.84,1.53 1.44,-0.21 2.75,-2.36 0.89,-2.47 2.9,-0.75 3.49,2.14 0.1,2.3 1.28,1 2.56,-1.58 1.7,-5.64 3.83,-0.89 1.36,-6.13 1.38,-2.51 3.34,-1.24 2.91,-0.23 0.49,-4.11 1.53,-2.28 2.06,-5.15 3.27,-1.01 0.72,-2.41 1.54,-4.1 2.38,-2.14 -2.77,-3.03 1.82,-1.8 2.65,1.32 3.12,0.48 2.6,-2.61 -0.25,-6.02 1.61,-2.94 2.32,-0.52 4.52,-3.76 3.31,-2.3 1.57,-1.19 2.67,-2.05 2.58,-3.36 2.8,0.51 1.34,-1.34 2.8,2.54 2.97,-2.29 -1.23,-3.19 1.03,-2.57 -0.24,-4.33 -3.03,-1.17 -2.78,1.52 -3.31,-1.52 -4.95,1.99 -4.11,2.05 -2.44,-1.07 -1.71,-1.95 -2.22,0.49 -4.37,-2.82 -3.18,-1.47 -3.9,1.47 -4.2,3.2 -0.76,4.04 -4.53,4.03 -0.76,4.29 -3.42,3.67 -7.22,-0.77 -5.48,-2.09 -0.77,-9.67 -3.17,-3.42 -4.77,-1.25 -2.97,-2.22 -2.63,0.95 -3.41,2.1 -3.18,-2.65z">
<title>Shandong Province</title>
</path>
<path id="pSX" :class="{ visited: visitedRegions.has('14') }" d="m700.91,327.25 -0.76,0.47 -1.72,3.77 -4.15,1.93 -4.2,3.15 -2.2,0.1 -2.62,-1.66 -1.92,0.57 -2.21,2.08 -0.99,2.05 -2.35,1.31 -4.79,-1.9 -2.26,0.89 -3.77,8.24 -1.83,5.1 -2.64,1.85 -3.83,-0.61 -1.18,1.88 -0.65,2.32 -2.53,2.08 -0.89,-0.18 -0.1,5.12 -0.37,2.38 -2.41,2.5 v5.53 l-1.01,2.51 -0.59,4.27 -3.55,3.09 -1.78,3.62 0.14,3.72 2.75,2.53 2.64,3.79 -0.1,2.76 -1.2,2.24 0.19,3.09 -3.53,6.66 -0.16,7.57 1.65,2.25 0.3,9.98 3.97,10.42 -0.34,3.24 -2.71,4.52 -1.89,5.69 0.33,7.25 1.07,2.17 5.82,0.18 3.23,-1.2 1.96,-2.64 4.77,-2.01 4.43,-0.83 5.32,-5.7 1.59,-0.74 2.37,-0.1 1.03,-2.64 2.92,-1.04 4.86,0.1 2.61,-2.17 2.76,0.88 1.67,-0.43 2.76,-2.32 5.82,-3.96 2.48,-2.41 0.27,-7.18 0.61,-2.92 -0.1,-7.04 -2.62,-2.42 -2.4,-3.34 0.36,-2.37 0.95,-0.75 1.07,-0.15 2.48,-3.62 -0.66,-3.13 0.27,-1.92 0.68,-1.16 0.64,-3.45 2.05,-3.12 1.04,-3.02 -0.95,-2.28 -4.38,-5.26 -1.27,-3.71 -3.83,-1.42 -1.16,-1.44 -0.69,-5.76 1.4,-1.77 1.39,-1.26 1.4,-1.67 0.1,-1.42 -1.15,-0.99 -0.32,-1.48 2.28,-2.64 4.22,-0.86 3.32,-1.82 0.5,-1.29 0.43,-3.88 1.22,-3.05 -0.99,-2.35 -2.1,-1.96 -0.55,-3.03 -1.04,-1.15 -3.41,-0.32 -2.03,-1.4 -0.49,-1.62 1.12,-2.53 3.28,-1.04 2.26,-1.97 v-0.7 l-2.58,-1.24 -0.56,-3.36z">
<title>Shanxi Province</title>
</path>
<path id="pSN" :class="{ visited: visitedRegions.has('61') }" d="m604.56,399.53 2.78,3.72 4.16,-0.28 2,-1.19 1.56,-4.78 2,-4.28 2.88,-2.03 3.09,-5.35 1.88,-1.59 1.37,-2.72 4.03,-1.16 1.47,-1.21 v-1.91 l-1.4,-1.72 0.75,-5.62 3.84,-3.63 1.62,-3.78 0.97,0.62 0.38,1 4.12,-0.68 2.72,1.47 1.06,-0.91 1,-1.84 3.69,-3.88 2.85,3.09 0.34,4.25 -0.38,2.94 -2.59,2.53 -0.1,5.44 -0.82,2.44 -0.53,4.37 -3.72,3.47 -1.78,3.41 0.16,3.37 2.91,3.19 2.43,3.72 v2.59 l-1.18,2.41 0.15,3 -3.5,6.66 -0.25,7.53 1.57,2.34 0.46,9.97 3.75,10.41 -0.31,2.96 -2.53,4.6 -1.87,5.78 0.25,7.34 1.18,2.25 0.88,3.57 1.81,1.84 0.41,2.12 2.72,1.35 0.93,4.31 -0.18,1.91 2.56,1.81 1.94,3.16 3.15,2.84 v4.81 l-3.94,4.47 -3.65,-2.62 -3,2.15 h-4.19 l-1.41,-0.75 -6.97,-0.78 -2.46,0.84 -0.79,1.1 0.6,1.75 3.75,0.5 0.62,3.28 4.28,0.94 2.69,1.81 -0.31,2.81 -3.28,0.66 -3.16,1.53 -2.78,0.4 -1.66,5.38 1.04,2.56 2.65,2.69 -0.84,2.37 v3.04 l-6.5,1.25 -1.85,-0.54 -0.72,-2.87 -4.81,-0.78 -8.12,-5.1 -3.85,0.32 -5.72,2.5 -5.59,-4.35 -2.94,-0.37 -2.09,-2.38 -2.13,1.16 -2.53,-0.28 -1.03,-1.53 -0.81,-3.16 -4.63,-0.47 -2,0.97 -8.71,2.13 -2.19,-1.22 -0.69,-3.41 -1.47,-0.91 -4.81,-0.34 3.41,-3.78 1.06,-3.84 -1.03,-2.6 -3.13,-1.69 1.35,-2.21 3.62,-1.72 7.44,-0.1 0.4,-0.9 -0.34,-1.16 v-4.47 l-1,-1.65 2.75,-6.22 1.5,-1.47 -0.1,-1.72 -2.22,-2.13 -3.91,-1.12 -0.19,-1.5 2.94,-2.66 0.47,-3 -0.97,-2.15 0.69,-2.19 4.84,-1.19 3.69,0.5 3.41,3.06 8.81,-1.53 1.91,-1.15 -1.29,-2.32 0.22,-3.5 1.35,-0.21 2.62,1.21 3.1,-1.65 5.53,0.31 2.09,-1.34 0.5,-4.75 -2.03,-2.72 -0.47,-4.63 3.25,-2.81 -0.28,-7.59 -2.56,-2.32 -1.85,-0.4 -3.9,-2.72 -2.69,0.75 -3.84,-3.75 -6.63,-1.91 -0.75,-0.68 -2.19,-0.5 -1.68,-4.22 0.53,-2.38 -1.44,-2.72 1.12,-5.25 2.6,-2.93 5.23,-1.36 3.99,-0.1 2.28,-1.67z">
<title>Shaanxi Province</title>
</path>
<path id="pAH" :class="{ visited: visitedRegions.has('34') }" d="m738.08,492.71 2.08,-1.58 0.93,-3.19 -0.68,-2.62 0.97,-3.27 3.91,-1.54 0.11,-1.22 -1.44,-5.57 0.58,-2.98 1.97,-1.07 2.66,0.21 2.08,2.05 3.27,3.88 1.54,-0.1 3.41,-2.08 1.15,-2.15 1.69,-0.97 0.57,-1.19 -1.97,-2.26 -0.22,-3.23 -0.9,-0.97 -2.94,-0.21 -4.09,-3.05 -0.29,-2.55 1.94,-0.47 2.04,-1.29 1.98,0.1 2.04,2.05 7.11,2.26 0.68,3.01 3.63,2.59 2.08,-0.25 2.95,0.82 h3.41 l2.9,2.87 0.65,2.01 1.44,0.72 1.75,-0.9 2.98,-0.93 0.94,0.58 v3.66 l-1.8,6.35 0.22,1.72 4.13,0.94 2.04,2.87 -0.18,1.44 1.47,2.83 2.09,1.58 5.17,-1.15 0.75,-1.36 0.39,-1.98 1.37,-2.01 1.04,-0.1 4.63,2.33 1.79,3.91 -2.15,3.77 -1.47,-0.25 -2.15,-1.62 -4.74,0.76 -0.4,1.58 1.65,2.04 0.86,1.98 -0.75,2.33 -2.3,1.83 -1.32,2.23 -0.33,2.01 1.33,2.04 2.12,1.69 3.3,1.15 1.01,1.08 2.87,0.82 v4.24 l-1.36,1.47 1.4,2.33 3.59,-0.32 2.94,-1.26 2.44,-0.25 2.27,1.33 4.23,0.5 v4.85 l-1.26,4.59 -1.36,1.83 -1.94,1.44 0.18,1.04 1.65,1.33 0.5,1.76 -1.51,1.9 -2.11,0.72 -3.77,-0.25 -1.19,0.93 0.29,3.73 0.47,0.76 0.32,4.81 -1.87,1.08 -0.5,3.26 -5.1,6.07 -1.76,0.5 -2.04,1.87 -2.3,-2.52 -2.01,-0.57 -2.55,0.97 -5.63,-0.5 -2.48,-1.65 -1.76,-2.52 -2.12,-0.32 -0.39,-0.68 -1.62,-0.29 -0.93,1.01 -0.4,3.05 -1.36,1.07 -2.01,3.49 -2.8,0.21 -1.22,-1.65 0.47,-1.9 2.04,-2.19 0.22,-1.9 -1.73,-2.41 -1.68,-0.9 -2.16,1.3 -0.64,1.83 -1.87,1.9 -5.38,2.4 -0.58,-2.9 -1.33,-4.71 -1.43,-2.72 -2.48,-1.69 0.22,-3.16 -2.3,-2.15 -1.37,-2.19 1.51,-2.95 1.9,-2.69 0.36,-1.62 -3.47,-2.54 -1.54,0.1 -2.24,-0.62 h-2.48 l-3.27,-3.39 0.71,-5.8 2.78,-3.02 3.97,-1.09 0.96,-7.06 -2.34,-6.66 0.11,-2.72 -2.06,0.92 -2.16,2.49 -1.94,-0.1 -3.15,-2.91 -3.13,-0.38 -0.87,-1.45 -0.19,-3.5 -1.52,-1.44 -4.09,-0.84 -0.69,-1.23 0.63,-1.91z">
<title>Anhui Province</title>
</path>
<path id="pJS" :class="{ visited: visitedRegions.has('32') }" d="m806.7,437.8 h-3.17 l-1.37,1.09 -1.88,0.32 -1.09,2.31 -1.28,6.12 -3.88,1.16 -1.59,5.28 -2.69,1.66 -1.53,-1.1 -0.1,-2.4 -2.97,-1.88 -3.16,0.69 -0.81,2.53 -3.28,2.72 -1.5,-0.19 -2,-1.43 -3.28,1.71 -1.82,-1.96 -0.97,-2.6 -4,-4.19 -2.56,-0.28 -4.53,1.91 -0.91,3.81 0.1,2.22 2.25,0.41 2.09,1.97 6.63,1.78 0.96,3.06 3.54,2.94 2.25,-0.22 6.96,1.06 2.19,2.16 0.63,2.47 1.06,0.4 4.84,-1.65 1.44,0.78 -0.16,3.47 -2,6.12 0.44,2.06 4.13,0.75 1.93,3 -0.12,1.66 1.5,2.47 2,1.65 5.37,-1.28 0.88,-3.43 2,-2.19 5.19,2.53 1.65,3.87 -2.03,3.85 -1.37,-0.19 -2.38,-1.72 -4.94,1 -0.43,1.44 1.75,1.81 1.03,2.44 -1,2.44 -2.16,1.4 -1.59,3.57 0.59,1.9 3.19,2.97 3.22,0.84 0.97,1.13 2.68,0.84 v4.25 l-1.28,1.5 1.25,1.94 h3.72 l2.66,-1.53 2.9,-0.1 2.32,1.46 4.22,0.32 1.9,-0.78 2.63,-0.32 6.43,4.19 2.66,-1.22 1.56,0.1 0.94,1.5 2,0.37 2.28,-1.84 0.81,-2.16 2.75,-2.06 0.82,-2.06 1.81,-1.32 0.81,-5.03 1.64,-2.85 -0.84,-0.47 -1.99,-2.25 -3.92,-0.73 -5.01,-0.8 -0.51,-2.78 -3.53,-0.7 -3.98,1.98 -1.3,0.44 -0.37,-0.52 1.65,-2.61 3.41,-1.57 4.98,0.52 1.79,2.55 2.65,0.97 h4.78 l3.61,0.51 3.54,2.03 4.46,0.74 2.1,-0.47 0.64,-1.27 -2.68,-3.65 -5.24,-4.74 -4.87,-1.28 -1.77,-5.07 -4.42,-1.72 -5.08,-1.27 -1.94,-1.39 0.77,-3.37 -1.22,-3.18 -6.06,-8.84 -3.75,-6.25 -4.81,-9.12 -2.47,-2.46 -12.38,-3.79 -2.26,-2.52 -5.65,-1.02 -0.55,-4.84z">
<title>Jiangsu Province</title>
</path>
<g id="pSH" :class="{ visited: visitedRegions.has('31') }">
<title>Shanghai Municipality</title>
<path id="pSH_1" d="m856.5,509.2 -1.62,2.26 -1.07,5.56 -1.62,1.44 -0.97,2.08 2.16,1.33 0.86,2.29 4.02,0.83 1.43,2.19 4.73,-3.4 3.24,-3.99 0.71,-3.83 -3.39,-2.91 -5.29,-2.01z"/>
<path id="pSH_2" style="stroke-width:0.5" d="m859.26,506.4 6.04,1.54 0.5,1.57 -3.96,-0.54 -3.91,-0.88 -3.55,-2.46 1.74,-1.12z"/>
<path id="pSH_3" style="stroke-width:0.5" d="m866.54,511.64 -0.1,0.67 -3.72,-1.33z"/>
</g>
<path id="pZJ" :class="{ visited: visitedRegions.has('33') }" d="m859.63,527.25 -1.69,-2.25 -3.88,-0.94 -0.56,-2.34 -2.13,-1.06 -2.78,1.71 -0.87,2.19 -2.44,2.19 -1.72,-0.63 -0.81,-1.59 h-2 l-2.31,1.31 -6.69,-4.4 -4.41,1.18 -0.12,5.5 -1.66,4.85 -2.9,2.84 2.43,3.69 -1.47,2 -2.87,0.81 -3.78,-0.25 -0.41,0.94 0.75,9.37 -1.84,1.1 -0.19,3.47 -5.41,5.87 -1.87,0.38 -3.31,4.43 -0.32,4.22 6.22,4.91 2.88,3.47 2,7.69 4.62,-0.29 1.5,1.22 0.35,3.32 -0.35,1.06 2.22,2.53 3,6.94 0.41,1.81 5.09,0.59 4.19,-2.53 1.44,-3.06 0.75,-0.84 1.47,0.56 2.9,5.09 2.06,1.28 5.66,-2.34 1.5,-0.94 3,0.56 2.18,1.43 1.59,-2.14 -0.25,-3.72 0.25,-2.32 1.78,-5.08 1.55,-3.62 1.73,-1.23 0.51,-6.1 3.46,-1.44 0.72,4.77 2.44,-3.34 3.15,-2.18 -1.92,-4.08 -1.87,-3.2 2.85,-2.59 v-3.51 l2.75,-3.75 -1.02,-3.07 1.77,-1.51 -0.97,-3.65 -0.43,-5.08 -1.43,3.49 -3.48,0.31 3.89,-5.27 4.31,-3.31 3.41,-1.7 -0.44,-2.21 -5.35,-2.19 -2.08,0.7 -1.51,3.52 -2.75,1.1 -3.39,-2.35 -4.48,-3.48 -3.6,0.48 -4.77,4.27 -2.63,1.06 -4.63,-0.77 -4.15,-1.04 -0.93,-1.58 3.54,-1.91 5.33,-0.51 2.85,-0.95 0.24,-2.97z">
<title>Zhejiang Province</title>
</path>
<path id="pJX" :class="{ visited: visitedRegions.has('36') }" d="m735.33,663.03 1.78,1.39 0.34,1.38 4.25,0.2 3.13,-1.78 2.75,-0.69 1.78,0.86 1.37,2.56 -0.84,2.53 -3.81,2.68 -1.05,3.92 -2.8,3.72 4.49,3.01 14.15,-5.5 5.52,-2.84 4.98,3.76 2.55,-0.14 0.67,-1.67 -1.43,-4 2.81,-2.12 -1.81,-3.78 -0.11,-2.29 1.65,-1.56 1.07,-9.31 1.42,-1.99 0.12,-3.56 2.6,-1.48 1.81,-3.89 -1.16,-4.16 3.22,-3.33 v-1.25 l-1.97,-3.95 0.48,-5.53 2.38,-1.83 4.67,-1.98 2.95,-4.91 -1.84,-6.03 2.14,-4.99 0.51,-3.15 3.79,-2.21 2,0.21 1.2,1.19 2.14,0.28 0.61,-1.8 3.06,-2.31 7.06,-3.36 -0.2,-2.99 1.8,-2.47 -2.02,-7.67 -3.28,-3.68 -5.95,-4.74 0.2,-3.75 1.72,-2.98 -2.34,-2.72 -2.18,-0.5 -2.2,0.89 -5.81,-0.36 -2.69,-1.92 -1.45,-2.19 -2.14,-0.23 -0.5,-1.08 -1.67,-0.13 -0.86,1.13 -0.54,3.04 -1.31,1.3 -1.89,3.25 -2.5,0.27 -1.44,-1.66 0.38,-2.09 1.97,-2.02 0.36,-2.25 -1.85,-2.2 -1.57,-0.67 -2.27,1.01 -0.55,2.08 -2.09,1.8 -9.56,4.7 -3.18,-1.55 -3.57,-0.2 -2.05,0.53 -0.47,3.44 -1.69,0.87 -2.62,-0.34 -1.39,1.02 0.72,1.82 -2.52,0.6 -2.16,1.95 -0.64,1.66 -5.98,2.06 -3.88,0.37 -1.23,1.77 -4.8,3.16 -0.34,1.48 4.87,6.31 0.13,4.25 2.48,3.92 -0.56,1.88 -2.17,2.3 -1.89,4.73 -3.69,1.28 -0.36,3.28 -1.48,2.19 -0.25,3.83 1.15,4.34 1.18,0.64 1.81,-1.39 1.34,1.11 0.46,1.3 -1.47,2.91 0.56,1.4 2.92,2.47 -1.58,3.27 0.53,1.95 2.35,2.01 2.56,0.83 0.38,2.96 -1.1,1.82 -0.4,3.66 1.51,0.7 2.13,-1.36 0.93,0.68 -2.5,3.34 0.14,3.09 -2.18,4.78 1.53,2.18z">
<title>Jiangxi Province</title>
</path>
<path id="pHB" :class="{ visited: visitedRegions.has('42') }" d="m661.22,496.26 2.44,2.24 3.59,5.78 3.09,1.78 2.22,3.34 3.61,0.43 1.94,1.72 3.98,0.85 5.87,2.01 4.72,-1.37 2.25,0.61 6.37,-2.17 3.08,-0.11 4.13,2.37 1.92,-0.93 1.74,-2.01 1.71,-0.7 1.02,0.57 0.41,6.97 1.24,2.33 4.11,3.66 1.48,-0.29 2.08,-1.49 3.43,1.93 2.4,-0.44 1.04,0.79 0.1,1.96 4.67,2.41 4.47,-0.78 1.52,-2.58 2.01,0.77 0.54,2.07 2.89,0.93 3.7,3.8 2.33,-0.43 4.06,0.99 3,2.14 -0.51,2.17 -3.3,4.83 1.89,3.19 1.84,1.31 -0.18,3.34 2.53,1.61 2.45,6.48 0.8,4.04 -4.47,2.12 -2.97,-1.49 -3.68,-0.41 -2.12,0.48 -0.34,3.39 -2.1,1.19 -2.28,-0.22 -1.22,0.99 0.46,1.8 -2.19,0.34 -2.33,2.1 -0.74,1.83 -5.9,1.92 -3.95,0.2 -1.6,2.24 -4.23,2.73 -0.77,1.42 -2.66,-0.53 -1.45,0.72 -0.6,-2.33 -1.77,-1.67 0.12,-3.18 1.24,-1.94 -0.59,-2.45 -2.08,-2.36 -0.24,-2.08 -3.98,2.89 -4.88,6.25 -2.88,-0.34 -0.61,-2.16 1.14,-2.81 -1.28,0.35 -1.18,-1.22 -2.23,0.81 -3.09,2.91 h-2.62 l-2.47,1.71 -9.18,-6.27 -8.79,-0.43 -3.16,-1.95 -5.67,-0.86 -3,0.32 -1.83,1.13 -3.62,0.65 -0.36,1.36 3.28,2.73 0.54,2.06 -4.04,2.51 h-3.37 l-1.83,0.59 -1.89,-2.65 -3.44,0.41 -3.38,2.35 -1.94,0.92 -3.28,2.99 -0.45,2.84 -1.81,2.24 -0.51,3.88 -2.85,-0.9 -4.18,-5.36 -0.29,-4.51 -2.91,-0.79 -3.1,-3.48 -2.35,1.56 0.77,-3.27 0.16,-7.61 -2.76,-3.64 3.93,-2.98 3.43,0.11 3.51,-1.83 3.13,0.28 3.89,-0.44 3.63,-2.12 4.65,-5.22 3.85,1.43 1.37,-3.14 -0.61,-3.48 1.04,-2.93 -0.88,-3.12 -1.42,-2.46 -3.19,-2.1 v-4.47 l-6.05,-0.45 0.18,-3.34 0.68,-1.99 -2.78,-2.94 -1,-2.25 1.86,-5.36 3.38,-0.63 2.44,-1.42 3.32,-0.64 0.5,-2.89 -2.82,-1.8 -4.61,-0.82 -0.3,-3.43 -3.76,-0.36 -0.66,-1.53 0.95,-1.33 2.57,-0.7 6.93,0.78 1.61,0.77 3.93,-0.15 2.52,-2.11 3.84,2.51z">
<title>Hubei Province</title>
</path>
<path id="pHN" :class="{ visited: visitedRegions.has('43') }" d="m635.62,590.87 0.54,-3.81 2.81,-5.81 2.62,-2.59 5.6,-3.41 3.4,-0.28 1.88,2.37 2.56,-0.59 2.81,0.25 3.72,-2.44 -0.5,-2.25 -3.47,-2.81 0.41,-1.34 3.84,-0.41 1.66,-1.56 8.44,0.56 3.59,2.16 8.63,0.43 9.31,6.47 2.5,-1.75 2.65,-0.53 4.32,-3.28 3.15,1.12 -0.78,2.38 0.53,2.16 2.75,0.31 4.94,-5.85 3.78,-3.46 0.56,2.37 2.04,2.78 0.5,1.88 -1.25,2.25 v2.9 l1.62,1.75 0.72,2.47 1.19,-0.65 3.09,0.46 4.63,6.1 0.4,4.62 2.53,3.63 -0.72,1.9 -2.18,2.6 -1.82,4.53 -2.75,0.78 -1.15,0.91 -0.19,3.09 -1.5,1.88 -0.31,3.93 1.34,4.53 1.06,0.38 1.79,-1.28 1.75,1.5 0.18,1.22 -1.78,2.56 0.66,1.31 3.12,2.53 -1.53,3.38 0.41,1.75 2.37,2.09 2.63,0.97 0.34,2.91 -1.12,1.78 -0.41,3.75 1.41,0.72 2.37,-1.57 0.75,0.66 -0.37,1 -2.22,2.38 0.12,3.06 -2.06,5 1.69,2.31 v2.81 l-2.97,2.72 -6.78,0.28 -4.1,-2.43 -6.03,4.75 v1.18 l1.31,2.19 -0.25,4.75 -3.15,0.38 -4.88,-4.22 -7.65,0.43 -0.72,4.32 0.9,2.09 -1.28,2.47 -2.9,1.03 -6.29,-0.19 -2.43,3.1 -0.75,0.34 -0.88,-1.34 0.31,-2.5 -0.71,-4.63 -1.75,-1.87 -2,0.15 -2.32,2.22 -1.9,1.94 -1.28,-1.5 0.1,-2.34 2.44,-3.44 0.97,-2.19 1.87,-1.69 0.63,-6.4 1.28,-1.53 0.22,-2.29 -1.35,-0.56 -2.65,0.5 -1.07,-1.75 0.63,-6.25 -2.66,-0.69 -1.59,-1 -2.16,0.25 -1.9,1.75 -4.35,-0.84 -1.81,2.91 -2.84,2.78 -1.1,1.94 -2.62,0.68 -1.07,-0.65 0.1,-3.16 -1.85,-1.75 -1.72,0.34 -1.59,2.97 -0.72,2.41 -1.97,1.97 -1.47,-0.31 -1.31,-1.32 h-2.75 l-0.47,-2.28 -3.09,-4 -0.25,-2.12 1.94,-2.57 0.12,-1.18 -1.94,-2.94 3.07,-2.91 0.31,-1.5 -0.53,-4.15 -1.6,-1.35 -2.31,-0.1 -1.78,0.81 -2.19,-0.12 -3,2.28 -1.4,-0.25 -1.35,-1.72 5.82,-6.09 3.12,-1.16 1.03,-1.81 1.56,-1.13 0.25,-2.31 -1.81,-2.44 -0.84,-3.84 -0.22,-5.53 0.37,-1.44 -1.43,-1.66 -1,-3.47z">
<title>Hunan Province</title>
</path>
<g id="pFJ" :class="{ visited: visitedRegions.has('35') }">
<title>Fujian Province</title>
<path id="pFJ_1" d="m804.56,695.18 -0.49,-0.99 -1.42,-0.94 -0.36,-1.42 -2.92,-5.11 -0.55,-4.88 -3.17,-4.34 -1.55,-1.11 -0.89,-2.66 -1.87,-0.21 -2.55,1.35 -2.78,-3.04 -2.88,-1.56 -2.89,0.78 -1.56,-0.88 -2.58,0.16 -1.97,-3.8 -0.1,-2.33 1.83,-1.5 0.8,-9.62 1.51,-1.71 v-3.79 l2.57,-1.3 2.06,-3.86 -1.3,-3.89 1.41,-2.12 1.75,-1.43 v-1.4 l-1.99,-3.44 0.47,-5.87 2.55,-2.04 4.36,-1.68 2.23,-2.96 0.93,-2.54 -1.63,-4.71 0.78,-3.95 1.16,-1.64 0.51,-3.31 2.43,-1.41 1.51,-1.12 1.89,0.39 1.14,1.42 1.96,0.15 0.95,-1.96 3.11,-2.07 6.94,-3.53 -0.21,-2.98 1.47,-2.35 4.77,-0.25 1.26,0.88 0.74,3.53 -0.5,1.02 2.29,2.57 1.77,4.77 1.59,3.11 0.16,0.95 3.59,0.28 1.22,0.43 4.05,-2.58 2.37,-4.07 1.47,0.77 3.3,5.05 2.05,1.18 2.46,-1.4 4.77,-1.86 2.75,0.53 2.04,1.45 -1.05,1.43 h-3.17 l2.16,1.55 -1.88,1.88 -0.26,3.51 -1.42,1.19 -3.36,2.33 -0.67,3.61 -0.73,-0.92 -3.6,-0.55 -0.86,3.14 3.87,3.35 0.91,1.59 -1.69,2.17 -1.31,4.2 1.52,2.54 -0.51,2.26 1.24,2.23 -2.28,3.54 2.3,3.33 -0.41,1.43 -2.01,-0.45 -2.91,-1.85 -1.95,2.23 -0.54,2.96 2.12,2.59 -1.99,0.66 -4.22,3.7 1.54,2.83 -0.88,1.53 -5.5,0.26 0.91,2.42 1.91,1.19 -0.92,2.07 -1.17,1.62 h-4.23 l-3.13,1.56 -1.75,2.5 -4.44,0.83 2.61,2.33 1.17,2.32 -1.92,1.92 -1.96,3.19 h-2.89 v4.22 l-3.87,-1.03 1.02,4.58 -2.64,-0.48 -0.77,3.56z"/>
<path id="pFJ_2" style="stroke-width:0.5" d="m850.41,617.37 -0.72,2.5 1.25,1.78 1.07,-2.14z"/>
<path id="pFJ_3" style="stroke-width:0.5" d="m848.98,643.08 -0.36,2.32 1.61,1.97 1.61,-1.79 -1.08,-2.14z"/>
</g>
<g id="pGD" :class="{ visited: visitedRegions.has('44') }">
<title>Guangdong Province</title>
<path id="pGD_1" d="m656.59,759.62 1.02,-3.28 2.41,-0.97 1.29,-3.96 1.41,-1.21 6.92,-0.83 -1.02,-1.64 0.15,-4.21 4.2,-0.65 3.53,-2.7 -1.45,-3.72 1.15,-2.39 4.17,-1.73 6.97,-6 1.53,-1.91 0.15,-3.51 -0.94,-2.16 -0.1,-4.14 1.72,-5.44 2.22,-2.01 0.28,-3.1 2.53,-0.76 2.22,-3.13 -0.75,-5.12 2.51,-2.47 0.1,-2.47 -0.91,-1.8 -0.14,-1.53 -1.25,-1.97 -0.11,-1.98 2.81,-1.03 1.74,-2.46 -1.06,-2.28 0.89,-4.06 7.57,-0.59 4.96,4.5 3.15,-0.5 0.16,-4.94 -1.62,-2.27 0.57,-1.5 5.93,-4.37 3.95,2.56 6.86,-0.41 3.03,-2.56 1.62,1.49 0.61,1.53 3.91,0.1 3.45,-1.95 2.66,-0.44 2.03,1.16 1.09,2.45 -0.9,2.61 -3.72,2.51 -0.97,3.68 -2.81,3.62 4.28,3.03 14.22,-5.08 4.29,-2.81 h1.44 l5.1,3.5 1.96,-0.25 0.94,-1.87 -1.28,-3.19 0.69,-1.59 3.81,-1.38 2.47,0.97 3.28,-0.66 2.81,1.6 2.41,2.9 3.5,-1.47 0.91,0.38 0.87,2.5 2.22,1.94 2.84,3.9 0.32,5.03 3.03,5.04 0.1,1.09 1.56,1.03 0.32,0.87 -1.98,2.83 1.9,1.67 -3.4,1.58 -5.77,0.51 -0.1,0.47 1.93,0.73 1.33,2.21 -3.92,1.72 -0.49,5.25 -4.67,0.74 -3.04,2.27 -2.27,0.51 -3.7,2.71 -4.09,-2.29 -1.18,1.48 -0.73,4.14 h-2.35 l-0.24,-2.18 -1.44,-0.86 -3.2,0.26 -3.62,3.37 -1.47,2.45 -2.92,0.22 -0.52,-3.9 -3.97,1.99 -0.26,3.57 -2.67,-1.26 -3.77,1.5 -3.93,1.35 -2.67,0.16 -2.24,-2.1 -1.04,-2.52 -2.28,0.21 -1.29,-1.28 -0.99,-0.74 -0.87,2.3 0.77,1.21 0.22,1.07 0.26,2.61 1.41,3.68 0.24,1.72 -0.11,0.19 -2.35,1.39 -2.39,-2.3 -0.4,0.28 1.24,3.07 -3.26,4.19 -3.45,-4.43 -1.14,2.56 0.39,5.7 h-3.86 l-4.26,3.01 -3.9,-1.04 -0.78,2.32 h-7.2 l-2.32,1.29 -3.18,1.06 v2.32 l-3.11,2.15 h-3.29 l-1.78,1.52 -5.58,0.26 -1.77,2.27 -4.05,0.26 -3.53,4.8 -2.49,0.25 -3.6,2.57 -2.39,2.4 1.09,3.54 2.76,1 0.75,3.48 3.49,3.49 -0.22,1.32 -3.41,3.4 -7.28,0.25 -0.66,-2.19 1.43,-1.13 -4.51,-2.39 -0.51,-5.85 -2.73,-0.74 0.97,-7.82 2.76,-4.26 1.44,-2.6z"/>
<g id="pGDi" style="stroke-width:0.5">
<path id="pGD_2" d="m672.55,767.9 -1.61,1.07 0.54,0.9 2.5,-0.18 0.53,-1.97z"/>
<path id="pGD_3" d="m731.85,739.93 -0.86,1.21 1.06,0.26z"/>
<path id="pGD_4" d="m719.1,749.28 v1.52 l1.24,0.5 0.1,-3.04z"/>
<path id="pGD_5" d="m716.27,749.7 -1.09,1.98 1.14,-0.1 0.88,-1.07z"/>
<path id="pGD_6" d="m701.17,754.08 -0.13,1.01 1.52,-0.76 v-1.89z"/>
</g>
</g>
<path id="pGX" :class="{ visited: visitedRegions.has('45') }" d="m567.75,725.59 7.16,-7.15 2.9,0.5 1.85,-0.66 0.59,-6.84 0.5,-1.47 -3.63,-4.53 -4.18,1.68 -4.6,-2.34 -3.25,2 -4.68,-2.19 -0.66,-3.93 -2.72,-3.19 -2.16,1.34 -1.28,-0.9 -3.25,0.28 -0.72,1.97 -1.4,-1 -2.6,-4.6 0.85,-2.4 4.34,1.15 5.28,-3.34 2.66,-3.6 5.81,0.72 1.78,2.78 3.94,0.44 2.13,1.31 2.09,-0.12 1.19,1.16 4.31,-2.75 -0.13,-3.85 2.82,-0.4 7.18,-4.94 3.91,-0.38 1.91,-1.87 1.53,-2.97 3.81,-3.56 1.47,0.81 0.87,2.66 2.82,2.09 2.59,-0.56 4.19,3.34 2.15,-1.47 2.54,-0.44 1.43,-3.81 1.6,-2.12 2.59,-1.32 4.75,2.97 2.41,-4.47 4.78,-0.12 1.03,-1.75 -1.56,-1.94 0.65,-1.15 2.25,-1.07 2.63,1.03 4.22,-5.75 2.37,-0.1 1.81,1.41 h1.5 l1.75,-1.85 0.66,-2.37 1.91,-3.06 1.5,-0.22 1.5,1.53 0.12,3.5 3.31,0.22 5.22,-6.44 1.03,-1.44 4.19,0.75 2.69,-2.09 5.69,1.84 -0.38,6.44 1.13,1.28 3.56,0.16 -0.1,2.34 -1.35,1.94 -0.47,6.22 -2.15,1.37 -0.47,2.35 -2.72,3.25 -0.31,2.4 1.62,1.66 3.94,-4.19 h2.06 l1.88,1.94 0.65,7.31 0.75,0.75 1.63,-1.03 1.16,-2.12 5.96,0.21 0.54,2.25 1.28,2.25 0.12,1.66 0.91,1.5 -0.28,2.09 -2.38,2.22 v2.35 l0.69,3.09 -2.25,3.09 -2.56,0.75 -0.38,3.07 -2.15,2.03 -1.63,5.53 0.1,4.25 1.1,2.16 -0.35,3.62 -5.56,5.5 -4.53,2.84 -2.63,0.88 -1.03,2.47 1.41,3.53 -3.69,2.87 -4,0.63 -0.22,4.09 0.85,1.47 -1.78,0.97 -4.57,0.22 -1.93,1.47 -1.19,3.81 -2.41,0.88 -0.9,3.21 h-0.51 l-3.08,-3.84 -1.66,0.34 1.02,4.3 -5.87,1.21 -1.51,1.09 -0.97,-3.83 -2.87,-0.78 -2.92,-1.6 -1.46,1.46 -2.31,-3.03 -0.82,-3.23 -3.2,0.87 v4.81 l-2.7,0.74 -1,2.23 h-1.76 l-0.58,-0.53 -3.51,1.39 -4.14,-2 -6.25,1.65 -7.97,-3.93 -2.4,-2.72 -6.53,-1.47 -1.35,-7.03 -1.53,-1.5 0.41,-3.13 3.43,-3.19 -0.34,-3.15 -5.41,-2.41 -4.21,1.6 -4.13,-2.82 -4.34,1.66 -7.35,-4.5z">
<title>Guangxi Autonomous Region</title>
</path>
<path id="pHI" :class="{ visited: visitedRegions.has('46') }" d="m658.26,794.33 5.18,0.89 3.22,-0.71 0.89,-1.61 6.61,-0.89 4.28,-1.25 4.82,-2.14 1.43,0.53 v3.57 l1.43,3.93 0.54,3.4 -2.5,2.14 -2.68,3.75 -2.68,5.71 -0.89,6.25 -0.72,4.65 -2.32,1.07 h-2.14 l-3.57,4.46 -0.18,1.97 -3.22,0.17 -3.57,0.9 v3.57 l-4.46,0.71 -2.14,-1.96 -6.08,0.36 -4.28,-1.97 -5.36,-2.32 -0.71,-4.29 -1.25,-3.03 -0.9,-4.82 0.9,-2.32 -0.72,-2.5 1.25,-2.68 7.68,-5.36 2.68,-0.71 1.43,-2.33 -2.5,-0.17 v-2.15 l2.14,-1.43 3.93,0.18 1.43,-0.71 v-1.79 l1.78,-0.89z">
<title>Hainan Province</title>
</path>
<!-- <g id="pHK" :class="{ visited: visitedRegions.has('91') }">
<path id="pHK_1" d="m744.14,728.48 3.91,-1.3 2.9,2.46 -1.91,1.18 0.51,1.6 -2.42,-0.44 -1.7,-0.45 -2.22,0.22z"/>
<path id="pHK_2" style="stroke-width:0.5" d="m744.14,734.29 -3.42,0.57 3.14,-2.31z"/>
<path id="pHK_3" style="stroke-width:0.5" d="m749.31,733.41 -0.97,0.82 -1.29,-1.06z"/>
</g>-->
<!-- <g id="pMO" :class="{ visited: visitedRegions.has('92') }">
<path id="pMO_1" d="m733.31,736.4 1.82,-1.39 -0.61,1.16z"/>
<path id="pMO_2" style="stroke-width:0.5" d="m735.77,736.48 -1.79,1.43 1.61,0.89z"/>
</g>-->
</g>
<g
id="layer7"
class="borders"
style="display:inline;fill:none;stroke-opacity:1">
<!-- <g
id="Claimed_borders"
style="stroke:#808080;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:2,4;">
<path id="bSouthTibet_719" d="m 300.89,635.01 3.56,0.29 4.07,-0.75 2.94,-1.01 2.67,2.03 3.47,0.18 3.38,0.75 3.45,-0.51 1.88,0.35 0.68,-0.22 6.61,-1.39 0.84,-3.36 3.25,-3 2.69,-1.59 2.74,-3.08 10.85,-2.16 3.01,-1.81 2.52,-0.62 1.99,-1.28 2.25,-0.8 1.44,-3.47 11.09,-3.47 0.71,1.39 1.54,1.04 2.9,-0.1 1.63,-0.64 1.28,2.04 1.53,0.31 0.33,-0.47 7.58,6.1 2.78,1.11 1.42,1.54 0.1,1.33"/>
<path id="bAksai_721" d="m 76.375,450.5 0.75,-3.63 h1.938 l0.25,-1.56 0.312,-0.87 -0.937,-2 v-1.44 l-0.375,-1.13 1.937,-1.37 1.625,1 0.813,-0.25 1.125,0.1 h1.437 l2.703,0.86 2.547,-1.8 -0.141,-1.4 0.329,-0.41 0.75,0.31 0.281,-0.56 0.05,-3.48 0.203,-0.85 1.078,-0.37 2.359,0.78 0.672,-0.55 -0.281,-1.29 0.359,-0.58 1.782,-0.19 1.921,-1.86 2.418,0.58 1.7,-2.72 1.69,-1.33 0.89,-3.68 0.11,-1.5 2.24,-1.82 0.37,-0.76 -0.15,-1.58 0.6,-1.03 1.68,-0.92 0.78,-2.04 -0.61,-0.5 -0.99,0.21 -0.96,-1.28 -0.85,-0.1 -0.89,1.69 -1.89,0.97 -0.78,-0.58 v-2.78 l-0.85,-1.76 -1.15,0.98 -0.75,-0.33 -0.27,-1.48 -1.81,-0.55 -0.654,-2.84 0.794,-0.72 -0.34,-0.83 -0.61,-0.14 -0.141,-0.8 -1.531,0.1 -0.969,-0.8 0.422,-1.55 -0.39,-0.68 -1.454,-0.54 -1.625,0.32 h-1.031 l-1.406,-0.43 -3.563,0.68 -1.406,-1.11 -1.328,-0.4 -1.172,0.26 -0.859,1.28 -3.016,0.91 -1.297,-0.14 -1.203,0.62 -1.453,0.13 -1.359,1.08 -1.188,0.1 -0.969,0.63 -0.406,0.97 -0.875,-0.13 -1.234,-0.84 h-0.625 l-0.953,1.06"/>
<path id="bAksai_723" d="m 77.688,471.22 0.723,-1.73 v-1.13 l0.6,-1.88 -0.458,-1.55 0.722,-1.05 -0.186,-2.29 -1.156,-1.4 1.125,-2.5"/>
<path id="bAksai_725" d="m 64.839,483.33 -3.09,-5.54 -0.78,0.12 -0.09,-1.69 1.438,-0.5"/>
<path id="bSouthAksai_727" d="m 71.339,503.36 -1.76,-0.1 -3.111,-1.14 -0.499,-1.29 -0.406,-1.9 -0.563,-1.57"/>
<path id="bSouthAksai_729" d="m 85.62,516.3 -0.541,-0.56 -1.018,-0.23 0.158,-2.95"/>
</g>-->
</g>
</svg>
</template>
<style scoped>
path{
fill: #888;
stroke: #ccc;
}
g.visited path,
path.visited {
fill: #4a90d9;
}
</style>
File diff suppressed because one or more lines are too long
+20
View File
@@ -0,0 +1,20 @@
// useFlights.ts
import {onMounted, ref} from "vue";
import {Flight} from "@/Types/types";
import axios from "axios";
export function useFlights(url: string) {
const flights = ref<Flight[]>([])
const flightsLoading = ref(true)
onMounted(async () => {
try {
const response = await axios.get(url)
flights.value = response.data
} finally {
flightsLoading.value = false
}
})
return { flights, flightsLoading }
}
@@ -0,0 +1,53 @@
// composables/useRegionFlights.ts
import {computed, Ref} from "vue";
import {Flight, Region} from "@/Types/types";
export function useRegionFlights(
flights: Ref<Flight[]>,
regionCodes: string[],
countryCode: string,
regions: Ref<Region[]>,
) {
const filteredFlights = computed(() => {
return flights.value.filter(flight => {
const depCode = flight.departure_airport?.region?.local_code
const depCountry = flight.departure_airport?.region?.country?.code
const arrCode = flight.arrival_airport?.region?.local_code
const arrCountry = flight.arrival_airport?.region?.country?.code
return (depCountry === countryCode && depCode && regionCodes.includes(depCode)) ||
(arrCountry === countryCode && arrCode && regionCodes.includes(arrCode))
})
})
const flightsByRegion = computed(() => {
return filteredFlights.value.reduce((grouped, flight) => {
const dep = flight.departure_airport?.region
const arr = flight.arrival_airport?.region
const regions = [
dep?.country?.code === countryCode ? dep?.local_code : null,
arr?.country?.code === countryCode ? arr?.local_code : null,
].filter((code): code is string => !!code && regionCodes.includes(code))
;[...new Set(regions)].forEach(code => {
if (!grouped[code]) grouped[code] = []
grouped[code].push(flight)
})
return grouped
}, {} as Record<string, Flight[]>)
})
const regionNames = computed(() => {
return Object.fromEntries(
regions.value
.filter(r => regionCodes.includes(r.local_code))
.map(r => [r.local_code, r.name])
)
})
const visitedRegions = computed(() => new Set(Object.keys(flightsByRegion.value)))
return { filteredFlights, flightsByRegion, visitedRegions, regionNames }
}
@@ -0,0 +1,83 @@
<script setup lang="ts">
import MainLayout from "@/Layouts/MainLayout.vue";
import {Achievement, Flight, Region, User} from "@/Types/types";
import Panel from "@/Components/FlightsGoneBy/Panels/Panel.vue";
import PanelHeader from "@/Components/FlightsGoneBy/Panels/PanelHeader.vue";
import Australia from "@/Components/Maps/Australia.vue";
import {computed} from "vue";
import PanelSubHeader from "@/Components/FlightsGoneBy/Panels/PanelSubHeader.vue";
import FlightRegionTable from "@/Components/FlightsGoneBy/FlightRegionTable.vue";
import {useRegionFlights} from "@/Composables/useRegionFlights";
import RegionLegend from "@/Components/FlightsGoneBy/Panels/RegionLegend.vue";
defineOptions({ layout: MainLayout })
const props = defineProps<{
achievement: Achievement
user: User
isFollowing: boolean
flights: Flight[]
regions: Region[]
}>()
const countryCode = 'AU'
const stateLocalCodes = ['WA', 'NSW', 'QLD', 'VIC', 'SA', 'TAS', 'NT', 'ACT']
const { flightsByRegion, visitedRegions, regionNames } = useRegionFlights(
computed(() => props.flights),
stateLocalCodes,
countryCode,
computed(() => props.regions)
)
</script>
<template>
<Panel>
<PanelHeader centered>The Challenge</PanelHeader>
<p>
Either take off or land from an airport in each Australian State and Internal Territory.
</p>
</Panel>
<Panel style="display:flex; flex-direction: column; align-items: center; justify-content: center;">
<PanelHeader centered>Progress</PanelHeader>
<Australia :visitedStates="visitedRegions" :flights="flightsByRegion" style="width: 100%;"/>
<RegionLegend :regionNames="regionNames" :visitedRegions="visitedRegions" :stateLocalCodes="stateLocalCodes"/>
<br/>
<PanelHeader center>Flights By State</PanelHeader>
<PanelSubHeader>5 Most Recent Flights By State</PanelSubHeader>
<FlightRegionTable
:regionCodes="stateLocalCodes"
:regionNames="regionNames"
:flightsByRegion="flightsByRegion"
/>
</Panel>
<Panel>
<PanelHeader centered>Requirements</PanelHeader>
<p>
The 8 states and territories you need to visit to complete this challenge are Queensland, Victoria, New South Wales, South Australia, Tasmania, Western Australia, the Northern Territory
and the Australian Capital Territory.
</p>
</Panel>
<Panel>
<PanelHeader centered>Difficulty</PanelHeader>
<p>
If you happen to be in Australia and have the time, this one is not so difficult to pull off. Australia is roughly the size of the continental United States but
instead of needing to visit 50 states, you have to visit just 8. The 6 states, and 2 internal territories.
</p>
<p>
All states and territories are reasonably well connected to each other by air and with very few exceptions it is usually possible
to get from any one state or territory to any other.
</p>
<p>
The capital city of each state acts as the de facto aviation hub for that state, but each state (with the exception of the ACT and South Australia)
has multiple commercial airports that are served from other states.
</p>
</Panel>
</template>
<style scoped>
</style>
@@ -0,0 +1,76 @@
<script setup lang="ts">
import MainLayout from "@/Layouts/MainLayout.vue";
import {Achievement, Flight, Region, User} from "@/Types/types";
import Panel from "@/Components/FlightsGoneBy/Panels/Panel.vue";
import PanelHeader from "@/Components/FlightsGoneBy/Panels/PanelHeader.vue";
import Australia from "@/Components/Maps/Australia.vue";
import {computed} from "vue";
import PanelSubHeader from "@/Components/FlightsGoneBy/Panels/PanelSubHeader.vue";
import FlightRegionTable from "@/Components/FlightsGoneBy/FlightRegionTable.vue";
import {useRegionFlights} from "@/Composables/useRegionFlights";
import RegionLegend from "@/Components/FlightsGoneBy/Panels/RegionLegend.vue";
import Canada from "@/Components/Maps/Canada.vue";
defineOptions({ layout: MainLayout })
const props = defineProps<{
achievement: Achievement
user: User
isFollowing: boolean
flights: Flight[]
regions: Region[]
}>()
const countryCode = 'CA'
const stateLocalCodes = [
'AB', 'BC', 'MB', 'NB', 'NL', 'NS', 'NT', 'NU', 'ON', 'PE',
'QC', 'SK', 'YT'
];
const { flightsByRegion, visitedRegions, regionNames } = useRegionFlights(
computed(() => props.flights),
stateLocalCodes,
countryCode,
computed(() => props.regions)
)
</script>
<template>
<Panel>
<PanelHeader centered>The Challenge</PanelHeader>
<p>
Either take off or land from an airport in each Canadian Province and Territory.
</p>
</Panel>
<Panel style="display:flex; flex-direction: column; align-items: center; justify-content: center;">
<PanelHeader centered>Progress</PanelHeader>
<Canada :visitedStates="visitedRegions" :flights="flightsByRegion" style="width: 100%;"/>
<RegionLegend :regionNames="regionNames" :visitedRegions="visitedRegions" :stateLocalCodes="stateLocalCodes"/>
<br/>
<PanelHeader center>Flights By State</PanelHeader>
<PanelSubHeader>5 Most Recent Flights By State</PanelSubHeader>
<FlightRegionTable
:regionCodes="stateLocalCodes"
:regionNames="regionNames"
:flightsByRegion="flightsByRegion"
/>
</Panel>
<Panel>
<PanelHeader centered>Difficulty</PanelHeader>
<p>
This challenge is not extremely difficult bur Canada's geography does complicate it and it could get expensive!
</p>
<p>
Canada's population is all in the South, so visiting the Northwest Territories, Yukon and Nanavut will likely require doubling back south to get connecting flights.
</p>
<p>
At least the capital of Ottawa is in Ontario - so there's no need to be chasing a special capital district like in Brazil, the US or Australia.
</p>
</Panel>
</template>
<style scoped>
</style>
@@ -0,0 +1,88 @@
<script setup lang="ts">
import MainLayout from "@/Layouts/MainLayout.vue";
import {Achievement, Flight, Region, User} from "@/Types/types";
import Panel from "@/Components/FlightsGoneBy/Panels/Panel.vue";
import PanelHeader from "@/Components/FlightsGoneBy/Panels/PanelHeader.vue";
import {computed} from "vue";
import PanelSubHeader from "@/Components/FlightsGoneBy/Panels/PanelSubHeader.vue";
import FlightRegionTable from "@/Components/FlightsGoneBy/FlightRegionTable.vue";
import {useRegionFlights} from "@/Composables/useRegionFlights";
import China from "@/Components/Maps/China.vue";
import RegionLegend from "@/Components/FlightsGoneBy/Panels/RegionLegend.vue";
defineOptions({ layout: MainLayout })
const props = defineProps<{
achievement: Achievement
user: User
isFollowing: boolean
flights: Flight[]
regions: Region[]
}>()
const countryCode = 'CN'
const stateLocalCodes = ['11','12', '13', '14', '15', '21', '22', '23', '31', '32', '33', '34', '35', '36', '37', '41', '42', '43', '44', '45', '46', '50', '51', '52', '53', '54', '61', '62', '63', '64', '65',]
const { flightsByRegion, visitedRegions, regionNames } = useRegionFlights(
computed(() => props.flights),
stateLocalCodes,
countryCode,
computed(() => props.regions)
)
</script>
<template>
<Panel>
<PanelHeader centered>The Challenge</PanelHeader>
<p>
Either take off or land from an airport in each Chinese Province, Autonomous Region or direct-administered municipality.
</p>
</Panel>
<Panel style="display:flex; flex-direction: column; align-items: center; justify-content: center;">
<PanelHeader centered>Progress</PanelHeader>
<China :visitedRegions="visitedRegions" style="width: 100%;"/>
<RegionLegend :regionNames="regionNames" :visitedRegions="visitedRegions" :stateLocalCodes="stateLocalCodes"/>
<br/>
<PanelHeader center>Flights By Region</PanelHeader>
<PanelSubHeader>5 Most Recent Flights Per Region</PanelSubHeader>
<FlightRegionTable
:regionCodes="stateLocalCodes"
:regionNames="regionNames"
:flightsByRegion="flightsByRegion"
/>
</Panel>
<Panel>
<PanelHeader centered>Requirements</PanelHeader>
<p>
China has 3 different types of administrative regions that are counted in this challenge.
</p>
<dl>
<dt>Province</dt>
<dd>There are 22 provinces in China.</dd>
<dt>Autonomous Regions</dt>
<dd>Not quite provinces as they have a bit more freedom. There are 5 autonomous regions to travel to for this travel.</dd>
<dt>Direct-Administered Municipality</dt>
<dd>There are 4 cities big enough to be their own subdivision - Beijing, Chongqing, Shanghai and Tianjin</dd>
</dl>
<p>
For this challenge, the regions are defined as by what would count as a domestic flight in China. Flights to Taiwan and the Special Administrative Regions of Hong Kong and Macau
do not count towards this challenge as China treats them as international flights. Disputed regions are also not counted.
</p>
</Panel>
<Panel>
<PanelHeader centered>Difficulty</PanelHeader>
<p>
China is very well connected by air, so for the most part getting to a new region is as simple as booking a flight. Basically all regions have multiple airports
that are well connected to many other regions.
</p>
<p>
The difficulty lies in the number of regions to get to, as well as the extremely good high speed rail in China - it often makes more sense to take the train then to fly.
</p>
</Panel>
</template>
<style scoped>
</style>
@@ -0,0 +1,83 @@
<script setup lang="ts">
import MainLayout from "@/Layouts/MainLayout.vue";
import {Achievement, Flight, Region, User} from "@/Types/types";
import Panel from "@/Components/FlightsGoneBy/Panels/Panel.vue";
import PanelHeader from "@/Components/FlightsGoneBy/Panels/PanelHeader.vue";
import Australia from "@/Components/Maps/Australia.vue";
import {computed} from "vue";
import PanelSubHeader from "@/Components/FlightsGoneBy/Panels/PanelSubHeader.vue";
import FlightRegionTable from "@/Components/FlightsGoneBy/FlightRegionTable.vue";
import {useRegionFlights} from "@/Composables/useRegionFlights";
import RegionLegend from "@/Components/FlightsGoneBy/Panels/RegionLegend.vue";
import USA from "@/Components/Maps/USA.vue";
defineOptions({ layout: MainLayout })
const props = defineProps<{
achievement: Achievement
user: User
isFollowing: boolean
flights: Flight[]
regions: Region[]
}>()
const countryCode = 'US'
const stateLocalCodes = [
'AL', 'AK', 'AZ', 'AR', 'CA', 'CO', 'CT', 'DE', 'DC', 'FL',
'GA', 'HI', 'ID', 'IL', 'IN', 'IA', 'KS', 'KY', 'LA', 'ME',
'MD', 'MA', 'MI', 'MN', 'MS', 'MO', 'MT', 'NE', 'NV', 'NH',
'NJ', 'NM', 'NY', 'NC', 'ND', 'OH', 'OK', 'OR', 'PA', 'RI',
'SC', 'SD', 'TN', 'TX', 'UT', 'VT', 'VA', 'WA', 'WV', 'WI', 'WY'
];
const { flightsByRegion, visitedRegions, regionNames } = useRegionFlights(
computed(() => props.flights),
stateLocalCodes,
countryCode,
computed(() => props.regions)
)
</script>
<template>
<Panel>
<PanelHeader centered>The Challenge</PanelHeader>
<p>
Either take off or land from an airport in each US State, plus the District of Colombia.
</p>
</Panel>
<Panel style="display:flex; flex-direction: column; align-items: center; justify-content: center;">
<PanelHeader centered>Progress</PanelHeader>
<USA :visitedStates="visitedRegions" :flights="flightsByRegion" style="width: 100%;"/>
<RegionLegend :visitedRegions="visitedRegions" :stateLocalCodes="stateLocalCodes" :regionNames="regionNames"/>
<br/>
<PanelHeader center>Flights By State</PanelHeader>
<PanelSubHeader>5 Most Recent Flights By State</PanelSubHeader>
<FlightRegionTable
:regionCodes="stateLocalCodes"
:regionNames="regionNames"
:flightsByRegion="flightsByRegion"
/>
</Panel>
<Panel>
<PanelHeader centered>Difficulty</PanelHeader>
<p>
This challenge is difficult - primarily due to the sheer number of states, but there are other complicating factors.
</p>
<p>
There are commercial flights to all 50 US States most of the time. Delaware has historically been the only exception to this rule, but more recently Wilmington has been served by low-cost airlines. If there are no commercial flights
to Delaware while attempting this challenge, you will have to try for a sightseeing flight!
</p>
<p>
Other compounding factors include sheer distance - Alaska and Hawaii might as well be in different countries if you are based on the East Coast.
</p>
<p>
Conversely, the US is really the only domestic aviation market that utilises the hub and spoke model to the extent that it does. This means you will inevitably transit in Atlanta or Dallas, and get a free point towards this challenge.
</p>
</Panel>
</template>
<style scoped>
</style>
@@ -0,0 +1,192 @@
<script setup lang="ts">
import {Achievement, Region, User, UserAchievement} from "@/Types/types";
import ProfileLayout from "@/Components/FlightsGoneBy/ProfileLayout.vue";
import Panel from "@/Components/FlightsGoneBy/Panels/Panel.vue";
import {computed, defineAsyncComponent} from 'vue';
import AchievementCard from "@/Components/FlightsGoneBy/AchievementCard.vue";
import PanelHeader from "@/Components/FlightsGoneBy/Panels/PanelHeader.vue";
import PanelSubHeader from "@/Components/FlightsGoneBy/Panels/PanelSubHeader.vue";
import {Head, Link} from '@inertiajs/vue3';
import MainLayout from "@/Layouts/MainLayout.vue";
import {useFlights} from "@/Composables/useFlights";
import InlineBadge from "@/Components/FlightsGoneBy/InlineBadge.vue";
import GlassTooltip from "@/Components/FlightsGoneBy/GlassTooltip.vue";
defineOptions({ layout: MainLayout })
const props = defineProps<{
achievement: Achievement
userAchievement: UserAchievement
user: User
isFollowing: boolean
flight_api_url: string
regions: Region[]
}>()
const { flights, flightsLoading } = useFlights(props.flight_api_url)
const AchievementDetail = defineAsyncComponent(
() => import(`./Achievements/${props.achievement.internal_name}.vue`)
)
const progress = computed(() => {
if (!props.achievement.progressive || !props.achievement.threshold) return null
const current = props.userAchievement?.progress ?? 0
return {
current,
threshold: props.achievement.threshold,
percentage: Math.min(Math.round((current / props.achievement.threshold) * 100), 100)
}
})
const unlocked = computed(() => {
if (!props.userAchievement) return false
if (props.achievement.progressive) return (progress.value?.percentage ?? 0) >= 100
return true
})
const difficultyVariant = computed(() => {
switch (props.achievement.difficulty?.internal_name) {
case 'easy': return 'easy'
case 'moderate': return 'moderate'
case 'hard': return 'hard'
case 'expensive': return 'expensive'
case 'near_impossible': return 'near-impossible'
case 'impossible': return 'impossible'
default: return 'economy'
}
})
</script>
<template>
<ProfileLayout :user="user" :isFollowing="isFollowing" :loading="flightsLoading">
<Head :title="`${achievement.name}`" />
<div class="innerLayout">
<v-btn
prepend-icon="mdi-arrow-left"
variant="flat"
>
<Link :href="route('profile.achievements', { user: user.name })">
Back to {{ user.name }}'s Achievements
</Link>
</v-btn>
<Panel>
<div class="achievement-hero">
<div class="achievement-icon-wrap" :class="{ unlocked }">
<v-icon
icon="mdi-trophy"
:color="unlocked ? 'amber' : 'grey'"
size="48"
/>
</div>
<div class="achievement-titles">
<div class="name-row">
<PanelHeader centered>{{ achievement.name }}</PanelHeader>
</div>
<PanelSubHeader>{{ achievement.short_description }}</PanelSubHeader>
<template v-if="achievement.progressive && progress">
<div class="progress-label">
<span>{{ Math.min(progress.current, progress.threshold) }} / {{ progress.threshold }}</span>
<span>{{ progress.percentage }}%</span>
</div>
<v-progress-linear
:model-value="progress.percentage"
:color="unlocked ? 'amber' : 'grey'"
rounded
height="8"
bg-color="white"
/>
</template>
<div v-else-if="unlocked" class="achieved-label">
<v-icon icon="mdi-check-circle" color="amber" size="16" /> Achieved
</div>
</div>
</div>
</Panel>
<component :is="AchievementDetail" :regions="regions" :flights="flights" :achievement="achievement" :user="user" :isFollowing="isFollowing" />
</div>
</ProfileLayout>
</template>
<style scoped>
.innerLayout{
display: flex;
flex-direction: column;
gap: 2em;
width: 60%;
max-width: 1000px;
margin: auto;
}
/* Tablet portrait */
@media (max-width: 1024px) {
.innerLayout {
width: 90%;
}
}
/* Mobile */
@media (max-width: 700px) {
.innerLayout {
width: 100%;
padding: 0 0.1rem; /* optional so content doesn't touch edges */
box-sizing: border-box;
}
}
.achievement-hero {
display: flex;
gap: 1.5rem;
align-items: flex-start;
}
.achievement-icon-wrap {
display: flex;
align-items: center;
justify-content: center;
width: 64px;
height: 64px;
border-radius: 50%;
background: rgba(255, 255, 255, 0.05);
flex-shrink: 0;
}
.achievement-icon-wrap.unlocked {
background: rgba(255, 193, 7, 0.15);
}
.achievement-titles {
flex: 1;
display: flex;
flex-direction: column;
gap: 0.5rem;
align-items: center; /* add this */
text-align: center; /* add this */
}
.name-row {
display: flex;
align-items: center;
gap: 0.75rem;
flex-wrap: wrap;
}
.progress-label {
display: flex;
justify-content: space-between;
font-size: 0.8rem;
opacity: 0.6;
}
.progress-label,
.v-progress-linear {
width: 100%;
}
</style>
+1
View File
@@ -72,6 +72,7 @@ const unlockedCount = computed(() =>
<div class="achievement-grid">
<AchievementCard
:user="user"
v-for="achievement in categoryAchievements"
:key="achievement.id"
:achievement="achievement"
+1 -1
View File
@@ -34,7 +34,7 @@ const props = defineProps<{
<div class="profile-grid">
<RoutePanel :flight="flight" />
<Panel label="Flight Details">
<BoardingPass :showToolTips="false" style="width:100%;max-width:600px" :flight="flight"/>
<BoardingPass :showToolTips="false" style="width:100%;max-width:600px; margin:0 auto" :flight="flight"/>
<DetailRows>
</DetailRows>
+2 -15
View File
@@ -10,6 +10,7 @@ import ProfileLayout from "@/Components/FlightsGoneBy/ProfileLayout.vue"
import DepartureBoard from "@/Components/FlightsGoneBy/DepartureBoard.vue"
import BoardingPasses from "@/Components/FlightsGoneBy/BoardingPasses.vue";
import FlightMapAndCharts from "@/Components/FlightsGoneBy/FlightMapAndCharts.vue";
import {useFlights} from "@/Composables/useFlights";
defineOptions({ layout: MainLayout })
@@ -23,19 +24,7 @@ const props = defineProps<{
}>()
// ── Flights state ─────────────────────────────────────────────────────────────
const flights = ref<Flight[]>([])
const flightsLoading = ref(true)
onMounted(async () => {
try {
const response = await axios.get(props.flight_api_url)
flights.value = response.data
} finally {
flightsLoading.value = false
}
})
const { flights, flightsLoading } = useFlights(props.flight_api_url)
const localSelectedFlightId = ref(props.selectedFlightId ?? null)
// ── Filter state ──────────────────────────────────────────────────────────────
@@ -90,7 +79,6 @@ const filteredFlights = computed(() => {
const stats = useFlightStats(filteredFlights)
watchEffect(() => {
console.time('all.charts.input')
const _ = [
stats.perYear.value,
stats.perMonth.value,
@@ -99,7 +87,6 @@ watchEffect(() => {
stats.topAirports.value,
stats.countries.value,
]
console.timeEnd('all.charts.input')
})
// ── View switching ────────────────────────────────────────────────────────────
+1
View File
@@ -98,6 +98,7 @@ export interface Achievement {
achievement_difficulty_id: number
category?: AchievementCategory
difficulty?: AchievementDifficulty
has_page: boolean
}
export interface UserAchievement {
+2 -1
View File
@@ -92,7 +92,8 @@ Route::domain(config('app.domain'))->group(
Route::get('/u/{user}/departure-board/{flight?}', [FlightProfileController::class, 'departureBoard'])
->name('profile.departure-board');
Route::get('/u/{user}/boarding-passes', [FlightProfileController::class, 'boardingPasses'])->name('profile.boarding-passes');
Route::get('/{user}/achievements', [AchievementController::class, 'index'])->name('profile.achievements');
Route::get('/u/{user}/achievements', [AchievementController::class, 'index'])->name('profile.achievements');
Route::get('/u/{user}/achievement/{achievement}', [AchievementController::class, 'specific'])->name('profile.achievement');
Route::get('/u/{user}/flight/{userFlight}', [FlightProfileController::class, 'flight'])->name('profile.flight');
require __DIR__.'/auth.php';