diff --git a/AMNet.Server/AMNet.Server.csproj b/AMNet.Server/AMNet.Server.csproj index 8b6259d..1ee4c27 100644 --- a/AMNet.Server/AMNet.Server.csproj +++ b/AMNet.Server/AMNet.Server.csproj @@ -3,7 +3,6 @@ true Library - false net9.0-windows Size true diff --git a/AMNet.Server/CardPresenter.cs b/AMNet.Server/CardPresenter.cs index 2d053a4..b2d18fe 100644 --- a/AMNet.Server/CardPresenter.cs +++ b/AMNet.Server/CardPresenter.cs @@ -13,11 +13,11 @@ internal class CardPresenter private readonly Lock _cardLock = new(); private StoredCard _currentCard; - public record StoredCard(byte[] Value, string OriginalValue, long ExpiresAt) + public record StoredCard(byte[] AccessCode, byte[] IDm, long ExpiresAt) { public bool Expired => Environment.TickCount64 >= ExpiresAt; - public override string ToString() => string.Join(" ", Enumerable.Range(0, 5).Select(x => OriginalValue.Substring(x * 4, 4))); + public override string ToString() => FormatHexCode(AccessCode); } /// @@ -31,10 +31,16 @@ internal class CardPresenter } } - public StoredCard TakeActiveCard() + public StoredCard TakeActiveCard(bool? requireIDm = null) { lock (_cardLock) { + // IDm and requireIDm are mutually exclusive + if (_currentCard == null || (requireIDm.HasValue && (_currentCard.IDm != null) ^ requireIDm.Value)) + { + return null; + } + var card = _currentCard; _currentCard = null; @@ -45,13 +51,14 @@ internal class CardPresenter /// /// Sets the card /// - /// The card id to set + /// The access code of the card to use + /// The FeliCa card IDm, if a physical card was used /// How long the card should be presented to the game for in milliseconds /// Whether the card was set successfully - public StoredCard SetCard(string cardId, long validFor = 5000) + public StoredCard SetCard(string accessCode, string idmHex, long validFor = 5000) { // ensure the matrix code is 20-digits long, otherwise pad with zeros - var matrixCode = cardId.Replace(" ", "").PadLeft(20, '0'); + var matrixCode = accessCode.Replace(" ", "").PadLeft(20, '0'); var bytes = new byte[10]; for (var i = 0; i < bytes.Length; i++) @@ -67,7 +74,8 @@ internal class CardPresenter } } - var card = new StoredCard(bytes, matrixCode, Environment.TickCount64 + validFor); + var idmBytes = !string.IsNullOrWhiteSpace(idmHex) && idmHex.Length <= 16 && idmHex.All(char.IsAsciiHexDigit) ? Convert.FromHexString(idmHex.PadLeft(16, '0')) : null; + var card = new StoredCard(bytes, idmBytes, Environment.TickCount64 + validFor); lock (_cardLock) { @@ -76,4 +84,9 @@ internal class CardPresenter return card; } + + /// + /// Formats a byte array as a hex string, inserting a space every 2 characters + /// + public static string FormatHexCode(byte[] code) => string.Join(" ", code.Chunk(2).Select(Convert.ToHexString)); } \ No newline at end of file diff --git a/AMNet.Server/Config.cs b/AMNet.Server/Config.cs index 954fd87..0018478 100644 --- a/AMNet.Server/Config.cs +++ b/AMNet.Server/Config.cs @@ -1,4 +1,5 @@ using System; +using System.Reflection; using Windows.Win32; using Windows.Win32.Foundation; @@ -6,25 +7,43 @@ namespace AMNet.Server; internal static class Config { - private const string ConfigFileName = @".\segatools.ini"; - internal const string IOSection = "aimeio"; + private const string ConfigFileName = @".\segatools.ini"; static Config() { GameId = ReadKey(IOSection, "gameId", 4); ServerName = ReadKey(IOSection, "serverName", 26, Environment.MachineName); - + + PhysicalCardUseIDm = PInvoke.GetPrivateProfileInt(IOSection, "useAimeDBForPhysicalCards", 0, ConfigFileName) > 0; EnableAimeTxt = PInvoke.GetPrivateProfileInt(IOSection, "enableKeyboardMode", 1, ConfigFileName) > 0; AimeTxtPath = ReadKey("aime", "aimePath", PInvoke.MAX_PATH, @"DEVICE\aime.txt"); } public static string GameId { get; } + + /// + /// The server name to show on devices. Defaults to the computer name. + /// public static string ServerName { get; } + + /// + /// Whether physically scanned cards should have their IDm forwarded to the game instead of the access code. + /// + public static bool PhysicalCardUseIDm { get; } + /// + /// Whether holding the enter key should trigger a card scan using the code from the aime.txt file + /// public static bool EnableAimeTxt { get; } + + /// + /// Path to the aime.txt file. Defaults to .\DEVICE\aime.txt + /// public static string AimeTxtPath { get; } + public static Version ServerVersion { get; } = new(Assembly.GetExecutingAssembly().GetCustomAttribute()?.Version ?? "1.0"); + internal static unsafe string ReadKey(string section, string key, uint maxLength, string @default = null) { // +1 for null terminator diff --git a/AMNet.Server/DllMain.cs b/AMNet.Server/DllMain.cs index e951608..099b46c 100644 --- a/AMNet.Server/DllMain.cs +++ b/AMNet.Server/DllMain.cs @@ -36,7 +36,7 @@ public static class DllMain CancellationTokenRegistration? cancellationRegistration = null; cancellationRegistration = App.Lifetime.ApplicationStarted.Register(() => { - App.Logger.LogInformation("AMNet Server ({gameId}) started successfully.", Config.GameId); + App.Logger.LogInformation("AMNet Server v{version} ({gameId}) started.", Config.ServerVersion.ToString(Config.ServerVersion.Build > 0 ? 3 : 2), Config.GameId ?? "SXXX"); App.Logger.LogInformation("Visit {addr} from a mobile device on the same network to get started.", WebAddress); // ReSharper disable once AccessToModifiedClosure @@ -71,7 +71,7 @@ public static class DllMain using var aimeTxtReader = new StreamReader(File.OpenRead(Config.AimeTxtPath), Encoding.UTF8); var fileName = Path.GetFileName(Config.AimeTxtPath); - var cardResult = App.Services.GetRequiredService().SetCard(aimeTxtReader.ReadLine()); + var cardResult = App.Services.GetRequiredService().SetCard(aimeTxtReader.ReadLine(), null); if (cardResult == null) { @@ -98,25 +98,43 @@ public static class DllMain return 1; } - var card = App.Services.GetRequiredService().TakeActiveCard(); + // if physical cards are being directed to + var card = App.Services.GetRequiredService().TakeActiveCard(Config.PhysicalCardUseIDm ? false : null); if (card?.Expired != false) { return 1; } - try - { - Marshal.Copy(card.Value, 0, luid, (int)luidSize); - return 0; - } - finally - { - App.Logger.LogInformation("Card read in: {cardId}", card); - } + Marshal.Copy(card.AccessCode, 0, luid, (int)luidSize); + App.Logger.LogInformation("Access Code read: {cardId}", CardPresenter.FormatHexCode(card.AccessCode)); + return 0; } [UnmanagedCallersOnly(EntryPoint = "aime_io_nfc_get_felica_id")] - public static unsafe int GetFelicaId(byte unitNo, ulong* idm) => 1; // felica not supported + public static unsafe int GetFelicaId(byte unitNo, ulong* idm) + { + if (!Config.PhysicalCardUseIDm || unitNo != 0) + { + return 1; + } + + var card = App.Services.GetRequiredService().TakeActiveCard(true); + if (card?.Expired != false) + { + return 1; + } + + ulong idmValue = 0; + for (var i = 0 ; i < 8 ; i++) + { + idmValue = (idmValue << 8) | card.IDm[i]; + } + + *idm = idmValue; + + App.Logger.LogInformation("FeliCa IDm read: {idm}", CardPresenter.FormatHexCode(card.IDm)); + return 0; + } [UnmanagedCallersOnly(EntryPoint = "aime_io_led_set_color")] public static void SetLedColour(byte unitNo, byte r, byte g, byte b) diff --git a/AMNet.Server/WebServer.cs b/AMNet.Server/WebServer.cs index e238f5b..0e3d127 100644 --- a/AMNet.Server/WebServer.cs +++ b/AMNet.Server/WebServer.cs @@ -1,5 +1,6 @@ using System; using System.Globalization; +using System.Linq; using System.Text.Json; using System.Text.Json.Serialization; using System.Threading; @@ -24,7 +25,11 @@ internal static partial class WebServer [property: JsonPropertyName("timeSinceLastPoll")] long? TimeSinceLastPoll); public record CardReadRequest( - [property: JsonPropertyName("cardId")] string MatrixCode); + [property: JsonPropertyName("cardId")] string AccessCode, + [property: JsonPropertyName("physicalCardIDm")] string PhysicalCardIDm); + + public record ServerErrorMessage( + [property: JsonPropertyName("message")] string Message); public static WebApplication BuildServer(params string[] listenAddresses) { @@ -97,23 +102,25 @@ internal static partial class WebServer } catch (JsonException e) { - ctx.Response.StatusCode = 400; - await ctx.Response.WriteAsync(e.Message); - + await WriteErrorResponse(ctx, StatusCodes.Status400BadRequest, e.Message); return; } - if (string.IsNullOrEmpty(request?.MatrixCode)) + if (string.IsNullOrEmpty(request?.AccessCode)) { - ctx.Response.StatusCode = 400; - await ctx.Response.WriteAsync("Card id not provided."); + await WriteErrorResponse(ctx, StatusCodes.Status400BadRequest, "Access Code not provided."); return; } - if (request.MatrixCode.Length is 0 or < 20) + if (request.AccessCode.Length is 0 or < 20 || !request.AccessCode.Any(char.IsAsciiDigit)) { - ctx.Response.StatusCode = 422; - await ctx.Response.WriteAsync("Invalid card id length."); + await WriteErrorResponse(ctx, StatusCodes.Status422UnprocessableEntity, "Invalid Access Code."); + return; + } + + if (request.AccessCode.All(x => x == '0')) + { + await WriteErrorResponse(ctx, StatusCodes.Status403Forbidden, "All-zero access codes are forbidden."); return; } @@ -122,26 +129,30 @@ internal static partial class WebServer if (currentCard?.Expired == false) { - var timeLeft = Math.Ceiling(TimeSpan.FromMilliseconds(currentCard.ExpiresAt - Environment.TickCount64).TotalSeconds); - - ctx.Response.StatusCode = 429; - ctx.Response.Headers.RetryAfter = timeLeft.ToString(CultureInfo.InvariantCulture); + ctx.Response.StatusCode = StatusCodes.Status429TooManyRequests; + ctx.Response.Headers.RetryAfter = Math.Ceiling(TimeSpan.FromMilliseconds(currentCard.ExpiresAt - Environment.TickCount64).TotalSeconds).ToString(CultureInfo.InvariantCulture); return; } - if (cardPresenter.SetCard(request.MatrixCode) != null) + if (cardPresenter.SetCard(request.AccessCode, request.PhysicalCardIDm) != null) { - ctx.Response.StatusCode = 202; + ctx.Response.StatusCode = StatusCodes.Status202Accepted; } else { - ctx.Response.StatusCode = 422; - await ctx.Response.WriteAsync("Invalid card id format."); + await WriteErrorResponse(ctx, StatusCodes.Status422UnprocessableEntity, "Invalid card id format."); } } - + + private static Task WriteErrorResponse(HttpContext ctx, int code, string message) + { + ctx.Response.StatusCode = code; + return ctx.Response.WriteAsJsonAsync(new ServerErrorMessage(message), SerializerContext.Default.ServerErrorMessage); + } + [JsonSerializable(typeof(SystemState))] [JsonSerializable(typeof(CardReadRequest))] + [JsonSerializable(typeof(ServerErrorMessage))] [JsonSourceGenerationOptions(WriteIndented = true, DefaultIgnoreCondition = JsonIgnoreCondition.Never)] private partial class SerializerContext : JsonSerializerContext; } \ No newline at end of file diff --git a/amnet-native/App.tsx b/amnet-native/App.tsx index eb28b85..df1e7b6 100644 --- a/amnet-native/App.tsx +++ b/amnet-native/App.tsx @@ -1,14 +1,14 @@ -import React, {useEffect} from "react"; +import React from "react"; import {StatusBar} from "expo-status-bar"; -import {useColorScheme, View} from "react-native"; import {Server, WalletCards} from "lucide-react-native"; +import {Platform, useColorScheme, View} from "react-native"; import {NavigationContainer} from "@react-navigation/native"; import {SafeAreaProvider} from "react-native-safe-area-context"; import {MD3Colors} from "react-native-paper/lib/typescript/types"; import {createBottomTabNavigator} from "@react-navigation/bottom-tabs"; import {createNativeStackNavigator} from "@react-navigation/native-stack"; -import {DefaultTheme as NavigationLightTheme, DarkTheme as NavigationDarkTheme} from '@react-navigation/native'; import {JetBrainsMono_400Regular, useFonts} from "@expo-google-fonts/jetbrains-mono"; +import {DefaultTheme as NavigationLightTheme, DarkTheme as NavigationDarkTheme} from '@react-navigation/native'; import { ActivityIndicator, adaptNavigationTheme, @@ -19,12 +19,15 @@ import { Paragraph } from 'react-native-paper'; -import RealmContext from "./models/RealmContext"; import linking from "./Linking"; +import RealmContext from "./models/RealmContext"; import {AMUITabBar} from "./components/AMUITabBar"; -import CardAddModal from "./app/CardAddModal"; + +import CardEditorModal from "./app/card/CardEditorModal"; +import CardAddModal from "./app/card/CardAddModal"; import ServerAddModal from "./app/ServerAddModal"; + import CardManagerStack from "./app/CardManagerStack"; import ServerManagerStack from "./app/ServerManagerStack"; @@ -118,7 +121,8 @@ export default function AppRoot() { - + + diff --git a/amnet-native/app.json b/amnet-native/app.json index 204526c..15e0e31 100644 --- a/amnet-native/app.json +++ b/amnet-native/app.json @@ -1,7 +1,7 @@ { "name": "AMNet", "scheme": "amnet", - "version": "1.2.0", + "version": "1.3.1", "slug": "amnet-native", "icon": "./assets/icon.png", "userInterfaceStyle": "automatic", @@ -12,7 +12,12 @@ "applinks:card.ppc.moe" ], "infoPlist": { - "UIViewControllerBasedStatusBarAppearance": "NO" + "UIViewControllerBasedStatusBarAppearance": "NO", + "NFCReaderUsageDescription": "AMNet uses NFC to scan Physical IC Cards", + "com.apple.developer.nfc.readersession.felica.systemcodes": ["0003", "88b4"] + }, + "entitlements": { + "com.apple.developer.nfc.readersession.formats": ["TAG"] }, "config": { "usesNonExemptEncryption": false @@ -20,7 +25,7 @@ }, "android": { "package": "moe.ppc.amnet", - "versionCode": 3, + "versionCode": 5, "adaptiveIcon": { "foregroundImage": "./assets/icon-android.png", "backgroundColor": "#DED8FD" diff --git a/amnet-native/app/CardAddModal.tsx b/amnet-native/app/CardAddModal.tsx deleted file mode 100644 index ca39332..0000000 --- a/amnet-native/app/CardAddModal.tsx +++ /dev/null @@ -1,124 +0,0 @@ -import {generateCardNumber} from "amnet-shared"; -import {useModalStyles} from "../utils/ModalStyles"; -import {useCallback, useLayoutEffect, useState} from "react"; -import {Platform, TextInput, TouchableOpacity, View} from "react-native"; -import {Button, Card, Divider, Paragraph, useTheme} from "react-native-paper"; - -import {AMCard} from "../models/AMCard"; -import RealmContext from "../models/RealmContext"; - -const {useRealm} = RealmContext; - -export default function CardAddModal({navigation, route}) { - const realm = useRealm(); - const theme = useTheme(); - const modalStyles = useModalStyles(); - - // state values - const [cardName, setCardName] = useState(''); - const [cardNumber, setCardNumber] = useState(''); - const [cardNumberReadOnly, setCardNumberReadOnly] = useState(false); - - const cardAddCallback = useCallback((cardId: string, cardName: string) => { - const duplicateCard = realm.objects("card").find(x => x.code === cardId); - - if (duplicateCard) { - realm.write(() => { - duplicateCard.name = cardName; - }); - } else { - realm.write(() => { - realm.create("card", AMCard.generate(cardId, cardName)); - }); - } - - navigation.goBack(); - }, [realm]); - - // header effects - if (Platform.OS === 'ios') { - useLayoutEffect(() => { - navigation.setOptions({ - headerLeft: () => navigation.goBack()}> - Cancel - , - }); - }, [navigation, modalStyles]); - } - - useLayoutEffect(() => { - const canSave = cardName.length && cardNumber.length === 20; - const themeOptions = canSave ? modalStyles.headerText : {color: theme.colors.outline}; - - navigation.setOptions({ - headerRight: () => cardAddCallback(cardNumber, cardName)}> - Save - - }) - }, [navigation, modalStyles, cardName, cardNumber]); - - // enable renaming by passing cardId to modal - useLayoutEffect(() => { - if (!route.params?.cardId) { - setCardNumberReadOnly(false); - return; - } - - setCardNumber(route.params.cardId); - setCardNumberReadOnly(true); - - if (route.params.cardName) { - setCardName(route.params.cardName); - } - - navigation.setOptions({ - title: "Edit Card" - }); - }, [route]); - - return ( - - - - - Card Name - - - - - - - - - Matrix Code - - setCardNumber(val?.replaceAll(/\D/g, '').substring(0, 20) ?? '')} - style={{...modalStyles.formItemInput, color: cardNumberReadOnly ? theme.colors.onSurfaceDisabled : theme.colors.onSurface}}/> - - - - - {/*only show card entry info when in create mode*/} - {!cardNumberReadOnly && ( - <> - - If you have a physical card, you can enter the 20-digit code on the back. - - - - - )} - ) -} diff --git a/amnet-native/app/CardManager.tsx b/amnet-native/app/CardManager.tsx index c6f9b7e..3d06aef 100644 --- a/amnet-native/app/CardManager.tsx +++ b/amnet-native/app/CardManager.tsx @@ -5,7 +5,7 @@ import {Button, useTheme} from "react-native-paper"; import {CreditCard, Plus} from "lucide-react-native"; import ContextMenu from "react-native-context-menu-view"; -import {AimeCard} from "../components/AimeCard"; +import {ICCard} from "../components/ICCard"; import {EmptyStatePlaceholder} from "../components/EmptyStatePlaceholder"; import {AMCard} from "../models/AMCard"; @@ -21,19 +21,20 @@ function CardEntry(props: { card: AMCard, navigation: any }) { } switch (indexPath.toString()) { - // copy card + // copy card access code case "0": + case "0,0": await Clipboard.setStringAsync(props.card.code); return; // edit card case "1,0": - props.navigation.navigate('add-card', {cardId: props.card.code, cardName: props.card.name}); + props.navigation.navigate('edit-card', {cardId: props.card._id.toHexString()}); return; // remove card case "1,1": - realm.write(() => realm.delete(props.card)); + AMCard.delete(realm, props.card); return; } }, [realm, props.card, props.navigation]); @@ -50,7 +51,7 @@ function CardEntry(props: { card: AMCard, navigation: any }) { {title: "Edit Card", systemIcon: "square.and.pencil"}, {title: "Delete Card", destructive: true, systemIcon: "trash"}] }]}> - + ); } diff --git a/amnet-native/app/ServerAddModal.tsx b/amnet-native/app/ServerAddModal.tsx index f772c35..f15a3dc 100644 --- a/amnet-native/app/ServerAddModal.tsx +++ b/amnet-native/app/ServerAddModal.tsx @@ -1,7 +1,7 @@ import {useModalStyles} from "../utils/ModalStyles"; import {Card, Paragraph, useTheme} from "react-native-paper"; import {useCallback, useEffect, useLayoutEffect, useState} from "react"; -import {Platform, TextInput, TouchableOpacity, View} from "react-native"; +import {Alert, Platform, TextInput, TouchableOpacity, View} from "react-native"; import RealmContext from "../models/RealmContext"; import {AMServer} from "../models/AMServer"; @@ -34,25 +34,48 @@ export default function ServerAddModal({route, navigation}) { let urlValid = false; try { - new URL(serverAddress); - urlValid = true; + const protocol = new URL(serverAddress).protocol; + urlValid = protocol.localeCompare("http:", undefined, {sensitivity: "case"}) === 0 || protocol.localeCompare("https:", undefined, {sensitivity: "case"}) === 0; } catch { // do nothing } const themeOptions = urlValid ? modalStyles.headerText : {color: theme.colors.outline}; navigation.setOptions({ - headerRight: () => saveServer()}> + headerRight: () => saveServer(serverAddress)}> Save }) }, [navigation, modalStyles, serverAddress]); - const saveServer = useCallback(() => { - let serverObject = realm.objects("server").find(x => x.serverAddress == serverAddress); + const saveServer = useCallback(async (address: string) => { + if (address.startsWith("https:")) { + await new Promise(done => { + Alert.alert( + "HTTPS Warning", + "By default, AMNet doesn't support HTTPS without advanced configuration. It's highly likely you won't be able to connect.", + [ + { + text: "Keep HTTPS", + style: "destructive", + onPress: () => done() + }, + { + text: "Change to HTTP", + isPreferred: true, + onPress: () => { + address = address.replace(/^https:/i, "http:"); + done(); + } + }, + ]); + }) + } + + let serverObject = realm.objects("server").find(x => x.serverAddress == address); if (!serverObject) { realm.write(() => { - serverObject = realm.create("server", AMServer.generate(serverAddress)); + serverObject = realm.create("server", AMServer.generate(address)); }); } @@ -60,7 +83,7 @@ export default function ServerAddModal({route, navigation}) { setTimeout(() => navigation.navigate('server', { serverId: serverObject._id.toHexString() }), 500); - }, [serverAddress, realm]); + }, [realm]); return ( @@ -85,7 +108,7 @@ export default function ServerAddModal({route, navigation}) { - If you're using HTTPS, ensure a trusted certificate has been configured via HTTP.SYS + AMNet uses HTTP by default. Unless has been configured to work with HTTP.SYS, HTTPS will not work. ) } diff --git a/amnet-native/app/ServerCardIn.tsx b/amnet-native/app/ServerCardIn.tsx index f91be2a..3305fd9 100644 --- a/amnet-native/app/ServerCardIn.tsx +++ b/amnet-native/app/ServerCardIn.tsx @@ -1,39 +1,32 @@ import {BSON} from "realm"; +import NfcManager from "react-native-nfc-manager"; import React, {useCallback, useEffect, useLayoutEffect, useMemo, useState} from "react"; -import {ActivityIndicator, Button, Paragraph, Title, useTheme} from "react-native-paper"; -import { - Alert, - Platform, - RefreshControl, - ScrollView, - Share, - StyleSheet, - Text, - TouchableOpacity, - View -} from "react-native"; +import {ActivityIndicator, Button, IconButton, Paragraph, Title, useTheme} from "react-native-paper"; +import {Platform, RefreshControl, ScrollView, Share, StyleSheet, Text, TouchableOpacity, View} from "react-native"; import { CircleCheck, CircleDot, CreditCard, - Nfc, Plus, SmartphoneNfcIcon, Share as ShareIcon, WifiOff, TvMinimalPlay, - Star + Star, + SmartphoneNfc, + SquareArrowOutUpRight } from "lucide-react-native"; import {EmptyStatePlaceholder} from "../components/EmptyStatePlaceholder"; import {AMUIStatusAlert} from "../components/AMUIStatusAlert"; import {AMUICardDetail} from "../components/AMUICard"; -import {AimeCard} from "../components/AimeCard"; +import {ICCard} from "../components/ICCard"; import RealmContext from "../models/RealmContext"; import {AMServer} from "../models/AMServer"; import {AMCard} from "../models/AMCard"; -import ObjectId = BSON.ObjectId; + +import {felicaCardReadAsync, icCard0008Number, ICType} from "../lib/iccard"; import { AMServerConnectionInfo, AMServerInstanceMetrics, @@ -42,6 +35,8 @@ import { performCardIn } from "amnet-shared"; +import ObjectId = BSON.ObjectId; + const {useRealm, useQuery, useObject} = RealmContext; export default function ServerCardIn({route, navigation}) { @@ -55,6 +50,16 @@ export default function ServerCardIn({route, navigation}) { query: q => q.sorted("lastUsed", true) }); + // nfc support + const [nfcSupported, setNfcSupported] = useState(Platform.OS === 'android' ? false : null); + useEffect(() => { + if (nfcSupported !== null) { + return; + } + + NfcManager.isSupported().then(setNfcSupported); + }, []); + // server state const [serverRefreshing, setServerRefreshing] = useState(false); const [serverReloadCounter, setServerReloadCounter] = useState(0); @@ -145,16 +150,21 @@ export default function ServerCardIn({route, navigation}) { } }, [serverId, serverReloadCounter, realm]); - const cardInCallback = useCallback(() => { + const cardInCallback = useCallback((card: AMCard) => { setCardInCompleted(false); const abortController = new AbortController(); - performCardIn(server, {cardId: selectedCard.code}, abortController.signal).then(async r => { + + performCardIn(server, { + cardId: card.code, + physicalCardIDm: card.physicalCardData?.cardIDm ?? undefined + }, abortController.signal).then(r => { const now = new Date(); realm.write(() => { server.lastUsed = now; - selectedCard.lastUsed = now; - selectedCard.lastUsedGameId = server.gameId; + + card.lastUsed = now; + card.lastUsedGameId = server.gameId; }); setCardInCompleted(r); @@ -166,7 +176,39 @@ export default function ServerCardIn({route, navigation}) { setTimeout(() => abortController.abort(), 5000); return () => abortController.abort(); - }, [server, selectedCard]); + }, [server]); + + const performPhysicalCardIn = useCallback(async () => { + const card = await felicaCardReadAsync(); + + if (!card) { + return; + } + + const savedCard = cards.find(x => x.physicalCardData?.cardIDm === card.idm); + + if (savedCard) { + setUserSelectedCard(savedCard); + cardInCallback(savedCard); + return; + } + + setCardInCompleted(false); + + const cardId = card.type !== ICType.Amusement ? icCard0008Number(card.idm) : card.accessCode; + const abortController = new AbortController(); + + performCardIn(server, {cardId, physicalCardIDm: card.idm}, abortController.signal).then(r => { + setCardInCompleted(r); + }).catch(() => { + setCardInCompleted(false); + }).finally(() => { + setTimeout(() => setCardInCompleted(null), 3000); + }); + + setTimeout(() => abortController.abort(), 5000); + return () => abortController.abort(); + }, [server]); const performRefresh = () => { setServerRefreshing(true); @@ -187,35 +229,51 @@ export default function ServerCardIn({route, navigation}) { } return ( - }> + }> - {server.gameId ? `Play ${getGameName(server.gameId)}` : "Selected Card"} + {server.gameId ? `Play ${getGameName(server.gameId)}` : "Selected Card"} {selectedCard ? <> - }> + }> {serverDefaultCard?.code == selectedCard.code && } - - + + + + {nfcSupported === true && ( + }/> + )} + : }/> - } + + } {cards.length > 0 && ( @@ -224,20 +282,20 @@ export default function ServerCardIn({route, navigation}) { {unselectedCards.length ? unselectedCards.map((card: AMCard) => ( - } - onPress={() => setUserSelectedCard(card)}> + } + onPress={() => setUserSelectedCard(card)}> {serverDefaultCard?.code == card.code && } - )) + )) : }/> diff --git a/amnet-native/app/ServerManager.tsx b/amnet-native/app/ServerManager.tsx index 9a36d98..356e63f 100644 --- a/amnet-native/app/ServerManager.tsx +++ b/amnet-native/app/ServerManager.tsx @@ -87,7 +87,7 @@ export default function ServerManager({navigation}) { q = q.filtered("serverName CONTAINS[c] $0 OR serverAddress CONTAINS[c] $0", searchQuery); } - return q.sorted("lastUsed"); + return q.sorted("lastUsed", true); }, [query, searchQuery]); // enable searchbar diff --git a/amnet-native/app/card/CardAddModal.tsx b/amnet-native/app/card/CardAddModal.tsx new file mode 100644 index 0000000..482fb24 --- /dev/null +++ b/amnet-native/app/card/CardAddModal.tsx @@ -0,0 +1,105 @@ +import NfcManager from "react-native-nfc-manager"; + +import React, {useEffect, useState} from "react"; +import {Platform, TouchableOpacity, View} from "react-native"; +import {createNativeStackNavigator} from "@react-navigation/native-stack"; + +import {Card, Paragraph, Text, Title, useTheme} from "react-native-paper"; +import {SmartphoneNfc, SquareAsterisk, SquarePlus} from "lucide-react-native"; + +import ManualCardEntry from "./ManualCardEntry"; +import PhysicalCardScan from "./PhyscialCardScan"; + +const Stack = createNativeStackNavigator(); + +function CardAddModal() { + return ( + + + + + + + ) +} + +function CardAddMethodSelector({navigation}) { + const theme = useTheme(); + const [nfcSupported, setNfcSupported] = useState(null); + + useEffect(() => { + NfcManager.isSupported().then(setNfcSupported); + }, []); + + return ( + + + Add new Card + + AMNet supports scanning physical cards, entering details manually or generating new ones. + + + + {nfcSupported !== null && ( + <> + } + disabled={!nfcSupported} + title="Scan Physical Card" + description={nfcSupported ? "Amusement IC or Transport cards supported" : "NFC is not supported on this device"} + onPress={() => navigation.navigate('Scan')}/> + + + + )} + + } + title="Enter Details Manually" + onPress={() => navigation.navigate('Manual')}/> + + } + title="Generate New Card" + onPress={() => navigation.navigate('Manual', {autoGenerate: true})}/> + + ) +} + +function MethodCard(props: { + title: string, + description?: string, + color: string, + disabled?: boolean, + icon: React.ReactElement, + onPress: () => void +}) { + const theme = useTheme(); + const large = props.description?.length > 0; + + return ( + !props.disabled && props.onPress()} disabled={props.disabled}> + + + + {React.cloneElement(props.icon, {size: large ? 24 : 16, color: theme.colors.surfaceVariant})} + + + {props.title} + {props.description && ({props.description})} + + + + + ) +} + +// the nfc library doesn't offer the same support for felica cards on android compared to ios... +export default Platform.OS === 'ios' ? CardAddModal : ManualCardEntry; diff --git a/amnet-native/app/card/CardEditorModal.tsx b/amnet-native/app/card/CardEditorModal.tsx new file mode 100644 index 0000000..19efa92 --- /dev/null +++ b/amnet-native/app/card/CardEditorModal.tsx @@ -0,0 +1,97 @@ +import {BSON} from "realm"; +import {Card, Divider, Paragraph, useTheme} from "react-native-paper"; +import {useCallback, useEffect, useLayoutEffect, useState} from "react"; +import {Platform, TextInput, TouchableOpacity, View} from "react-native"; + +import {useModalStyles} from "../../utils/ModalStyles"; + +import {AMCard} from "../../models/AMCard"; +import RealmContext from "../../models/RealmContext"; + +const {useObject, useRealm} = RealmContext; + +export default function CardEditorModal({navigation, route}) { + if (!route.params || !route.params.cardId) { + navigation.goBack(); + return; + } + + const theme = useTheme(); + const modalStyles = useModalStyles(); + + const realm = useRealm(); + const card = useObject(AMCard, BSON.ObjectId.createFromHexString(route.params.cardId)); + + const [cardName, setCardName] = useState(''); + + const updateCardCallback = useCallback((newName: string) => { + realm.write(() => { + card.name = newName; + }); + + navigation.goBack(); + }, [realm, navigation]); + + useEffect(() => { + if (card?.isValid() !== true) { + navigation.goBack(); + return; + } + + if (!cardName.length) { + setCardName(card.name); + } + }, [card]); + + // header effects + if (Platform.OS === 'ios') { + useLayoutEffect(() => { + navigation.setOptions({ + headerLeft: () => navigation.goBack()}> + Cancel + , + }); + }, [navigation, modalStyles]); + } + + useLayoutEffect(() => { + navigation.setOptions({ + headerRight: () => updateCardCallback(cardName)} disabled={!cardName.length}> + Save + + }); + }, [cardName]); + + return ( + + + + + + Card Name + + + + + + + + + Access Code + + + + + + + ) +} \ No newline at end of file diff --git a/amnet-native/app/card/ManualCardEntry.tsx b/amnet-native/app/card/ManualCardEntry.tsx new file mode 100644 index 0000000..ed8b34c --- /dev/null +++ b/amnet-native/app/card/ManualCardEntry.tsx @@ -0,0 +1,127 @@ +import {generateCardNumber, DecodeAMAccessCode} from "amnet-shared"; +import {useCallback, useEffect, useLayoutEffect, useState} from "react"; +import {Alert, Platform, TextInput, TouchableOpacity, View} from "react-native"; +import {Button, Card, Divider, Paragraph, useTheme} from "react-native-paper"; + +import {AMCard} from "../../models/AMCard"; +import RealmContext from "../../models/RealmContext"; +import {useModalStyles} from "../../utils/ModalStyles"; + +const {useRealm} = RealmContext; + +export default function CardAddModal({navigation, route}) { + const realm = useRealm(); + const theme = useTheme(); + const modalStyles = useModalStyles(); + + // state values + const [cardName, setCardName] = useState(''); + const [cardNumber, setCardNumber] = useState(''); + + const cardAddCallback = useCallback(async (cardId: string, cardName: string) => { + try { + // validate AM card numbers + cardId.startsWith('5') && DecodeAMAccessCode(cardId); + } catch { + const shouldContinue = await new Promise(done => { + Alert.alert( + "Invalid Access Code", + "It looks like the access code isn't from an Amusement IC card. Please double-check the code, and if it's correct, note that some networks might still reject it.", + [ + { + style: "destructive", + text: "Continue Anyway", + onPress: () => done(true) + }, + { + style: "cancel", + text: "Cancel", + onPress: () => done(false) + } + ], { + cancelable: true, + onDismiss: () => done(false) + }); + }) + + if (!shouldContinue) { + return; + } + } + + const duplicateCard = realm.objects(AMCard.schema.name).find(x => x.code === cardId); + + if (duplicateCard) { + realm.write(() => { + duplicateCard.name = cardName; + }); + } else { + realm.write(() => { + realm.create(AMCard.schema.name, AMCard.generate(cardId, cardName)); + }); + } + + if (Platform.OS === 'ios') { + navigation.getParent()?.goBack(); + } else { + navigation.goBack(); + } + }, [realm]); + + useLayoutEffect(() => { + const canSave = cardName.length && cardNumber.length === 20; + const themeOptions = canSave ? modalStyles.headerText : {color: theme.colors.outline}; + + navigation.setOptions({ + headerRight: () => cardAddCallback(cardNumber, cardName)}> + Save + + }) + }, [navigation, modalStyles, cardName, cardNumber]); + + // check params for autoGenerate request + useEffect(() => { + if (route.params?.autoGenerate) { + setCardNumber(generateCardNumber()); + } + }, []); + + return ( + + + + + + Card Name + + + + + + + + + Access Code + + setCardNumber(val?.replaceAll(/\D/g, '').substring(0, 20) ?? '')} + style={{...modalStyles.formItemInput, color: theme.colors.onSurface}}/> + + + + + + + ) +} diff --git a/amnet-native/app/card/PhyscialCardScan.tsx b/amnet-native/app/card/PhyscialCardScan.tsx new file mode 100644 index 0000000..67fadb8 --- /dev/null +++ b/amnet-native/app/card/PhyscialCardScan.tsx @@ -0,0 +1,84 @@ +import {useNavigation} from "@react-navigation/native"; +import {Card, Paragraph, useTheme} from "react-native-paper"; +import {useCallback, useLayoutEffect, useState} from "react"; +import {TextInput, TouchableOpacity, View} from "react-native"; + +import {useModalStyles} from "../../utils/ModalStyles"; + +import RealmContext from "../../models/RealmContext"; +import {AMCard, AMPhysicalCardData} from "../../models/AMCard"; +import {felicaCardReadAsync, icCard0008Number, ICType} from "../../lib/iccard"; + +const {useRealm} = RealmContext; + +export default function PhysicalCardScan() { + const realm = useRealm(); + const theme = useTheme(); + const navigation = useNavigation(); + const modalStyles = useModalStyles(); + + const [cardName, setCardName] = useState(''); + + const handleScan = useCallback(async () => { + const cardInfo = await felicaCardReadAsync(); + + if (!cardInfo) { + return; + } + + realm.write(() => { + // check if the card has already been registered (convert a manually entered card to a physically scanned card) + const accessCode = cardInfo.type === ICType.Amusement ? cardInfo.accessCode : icCard0008Number(cardInfo.idm); + const cardEntity = realm.objects(AMCard.schema.name).find(x => x.code === accessCode) ?? realm.create(AMCard.schema.name, AMCard.generate(accessCode, cardName)); + + // set physical card props + cardEntity.name = cardName; + cardEntity.added = new Date(); + cardEntity.physicalCardData ??= realm.objectForPrimaryKey(AMPhysicalCardData.schema.name, cardInfo.idm) ?? realm.create(AMPhysicalCardData.schema.name, { + cardIDm: cardInfo.idm, + cardType: cardInfo.type, + cardVendor: cardInfo.type === ICType.Amusement ? cardInfo.vendor : null + }); + }); + + // dismiss the parent screen (this screen can only be accessed from modal -> stack) + navigation.getParent()?.goBack(); + }, [realm, navigation, cardName]); + + useLayoutEffect(() => { + const canSave = cardName.length; + const themeOptions = canSave ? modalStyles.headerText : {color: theme.colors.outline}; + + navigation.setOptions({ + headerRight: () => handleScan()}> + Scan + + }) + }, [navigation, modalStyles, cardName]); + + return ( + + + + + + Card Name + + + + + + + + Ensure you have either an Amusement IC or Transport card ready to scan. + After the scan has completed, the card will be saved to your device. + + + ) +} \ No newline at end of file diff --git a/amnet-native/components/AimeCard.tsx b/amnet-native/components/AimeCard.tsx deleted file mode 100644 index 78adb2f..0000000 --- a/amnet-native/components/AimeCard.tsx +++ /dev/null @@ -1,36 +0,0 @@ -import {ReactNode, useMemo} from "react"; -import {Text} from "react-native"; -import {CreditCard, History} from "lucide-react-native"; - -import TimeAgo from "./TimeAgo"; -import {AMCardData} from "../models/AMCard"; -import {AMUICard, AMUICardActionProps, AMUICardDetail} from "./AMUICard"; - -export interface AimeCardProps extends AMUICardActionProps { - card: AMCardData, - children?: ReactNode, - showFullCardNumber?: boolean -} - -export function AimeCard(props: AimeCardProps) { - const displayedCardNumber = useMemo(() => props.showFullCardNumber - ? props.card.code.match(/.{1,4}/g)?.join(" ") - : `•••• ${props.card.code.substring(props.card.code.length - 4)}`, - [props.showFullCardNumber, props.card.code]); - - return ( - - - - {displayedCardNumber} - - {props.card.lastUsed && ( - - - - - )} - {props.children} - - ); -} \ No newline at end of file diff --git a/amnet-native/components/ICCard.tsx b/amnet-native/components/ICCard.tsx new file mode 100644 index 0000000..4c5e46d --- /dev/null +++ b/amnet-native/components/ICCard.tsx @@ -0,0 +1,85 @@ +import {Text} from "react-native"; +import {ReactNode, useMemo} from "react"; +import {CreditCard, History, Joystick, RailSymbol} from "lucide-react-native"; + +import TimeAgo from "./TimeAgo"; +import {AMUICard, AMUICardActionProps, AMUICardDetail} from "./AMUICard"; + +import {AMCardData, AMPhysicalCardData} from "../models/AMCard"; +import {AmusementICVendor, ICType} from "../lib/iccard"; + +export interface ICCardProps extends AMUICardActionProps { + card: AMCardData, + children?: ReactNode, + showFullCardNumber?: boolean +} + +export function ICCard(props: ICCardProps) { + const displayedCardNumber = useMemo(() => props.showFullCardNumber + ? props.card.code.match(/.{1,4}/g)?.join(" ") + : `•••• ${props.card.code.substring(props.card.code.length - 4)}`, + [props.showFullCardNumber, props.card.code]); + + return ( + + + + + + {displayedCardNumber} + + + {props.card.lastUsed && ( + + + + + )} + {props.children} + + ); +} + +function PhysicalICInfo(props: { physicalCard: AMPhysicalCardData | null }) { + if (props.physicalCard?.cardType === ICType.Transport) { + return ( + + + Transport IC Card + + ) + } + + if (props.physicalCard?.cardVendor) { + return ( + + + + {props.physicalCard.isBootlegAmusementCard ? "Bootleg " : null}{ICVendorName(props.physicalCard.cardVendor)} + + + ); + } + + return null; +} + +function ICVendorName(vendor: AmusementICVendor): string { + switch (vendor) { + case AmusementICVendor.Sega: + return "AiMe Card"; + + case AmusementICVendor.Konami: + return "e-Amusement Pass"; + + case AmusementICVendor.BandaiNamcoGames: + case AmusementICVendor.BandaiNamcoEntertainment: + return "Banapass"; + + case AmusementICVendor.Nesica: + return "NESiCA Card"; + + default: + return "Amusement IC Card"; + } +} diff --git a/amnet-native/lib/iccard-crypto.ts b/amnet-native/lib/iccard-crypto.ts new file mode 100644 index 0000000..d474aec --- /dev/null +++ b/amnet-native/lib/iccard-crypto.ts @@ -0,0 +1,49 @@ +import {Buffer} from "buffer"; + +const s_box_inv = [ + "243cba36e385a4d0934373b9706ec9f1100e9b2c97e70b636c2920fe86f3e1f5f69fb616047b8fabb1392a1beb5ca8ac3811125f893e7dcaec53db6d1ed281789646fff9541c287a4fd3c0dcc16af2bccb57fd4ae4f0b2c79540625241e2ad49a6b51f02c8da92e5b0c564764821de0f45584cdfa784cfd5154e27806b7ffc44714722dd300ca13be037a03523903274bf8dc2ead650bbd9c483b43168558b5df47218b7eff7982d010361cc0a8e1300e814af095175a52f1d0d658acd66073d05d84be99d997c91d1b819c32b426988c679173a4d5ba25afb253fbdf8edcee687a326a92ebe94087e67608c9c5e6fb39e06fa82aeee5977d71a9a34d456aa33", + "f9817c00b93037d590516ef0b206fbcd39145ff81bc74a82708c921deac34ec812e6b610d32f95842542a572e58f55ef86a253aeed262047de786828e445cc35bc3ebb8ec0be34afa60964017b44f5f3b13fa4b33280c94f6f40bf214c74e1115eeb3d712e9d6275d41648771367ad6b5d0787f7a89a59768b9b1ed8eeaae9992dc597f1a783fccadcbab84be88917050ba06523d1ce3603d7e0f291df0e9c2c0d66d673585cb40a4dc23bd2b7e2ac33db6027bd56432404028d7d7ff6b5f4fddd5bec79c4221fa18854e71998947e31a329e35acb6ab0cf6d936c7a08a93c1cd06350c68538c14149ab61522a9fd9181a57462b69dafaff0f15963a8afe9e0c", + "11a29ac394a051015bf7d130ee1f06d57767d3c16ee76a1aa48e9f6566d60c2dc6e469b7565a5760fc791ee11652f007d0cdca78c98bb38827f6e0c084cf2fa304008040a7fa759d4b89462228373413ff20b4da08266c8ff25d7b735c4c9071418a9ebb12e8556d2a254aafbd9519a531baadd9c5a66b83c4b6a9ccf9a1b17adcc7db2e7e7f8d4e620f0339fdb8d418c2ec6102531c3b7dbc1d59f58c98f16f9385f82c74d85e4d97ab87820a21425f0d5833443adde9fb5047c8d7819be51b1754862beff429320e7c2315ebe63c35e296683f0b43cede9cbe4f457276b510e3df92d2a84891b9acbf49b2996470eaf33e6314aeedaa24fe3dcbb009383605", + "c4f02849554af5fd75af2069c843866bc9a8c6544cdd025be89b597734d7c0515ff37ed4f19081ce198a7833cd978cd66a4b8fa480dc1a1714c5078766ad9d85b2f88d98df3e1f3f645840ac6c5c085d53baffd2a92c25abe432389af9cbc29167d0e322292d9248b40e9905a36f0a15efd5104fd8f600e6462b31578394ae03eb8e1324a11e5ed126d9a7ca366e7137eeb1fa7c7606b823be21bc9ec1da7a3b62277bb0e56318827f0feda02a9cbf11bde0880d3a795256f7b6d309161b70b342602f1ca29f72124547bbe10b018b1ddeec0c4ee9cfcc9574f4a593c7db4dfb3565fee739b5ea96c304414484fc6d30e2f268b7897d733db95a50a63c61aa2e", + "1a599cadc8e41154ed370f3ae65f3c4bb81589b1e8da697791568bdb0624cf18f8b087df8c35cb86539da4664a7a710a4838ffdc8320ce9832f6d7af705e738a14721ec129790708e94346d02fde2a4f3d2c50b375fc0b64ae317b61a530a093d2bec255ba6cf36268fdac3b95491f6bb485f7a603ec6e9a81090c6aee9e4ef0ab2d7ea1e1bbc9bc41f2fa2e1bdd2734d36004b501d640f9d50247d9d8e08f2bfbb7c5eb5716e5788df400cd8239c696bdbfe336450e261d63e7843eb69b22a3f58e236dc3997d9097102580d44ce274ccb25c33c7ea05123f51a8fef11c42cad176286f92a767a919a2445baaef587f21c08865b95d4d0d5ac413527c9f9417", + "c72b82615bd09684d34a70a19b59339fc02014532917c50bc97b97020d3a1e7c3f6b52e8753df6e40c8a4fc35f2665733123284874aaa73609b1e291045122fc08a605a4f1121c19eb4037c2a0411dd4dc07438f47afd12e98ab01baf06668acf9e769b6cb8d78871503d5dfa31a9d6aea2f944e9e42d7b83892d8bbdedd9abcb04c79f4583ee98381ffe355fd5db2ef9c6d549960da3becfa11d6c42aed4bae13bfb9068be01f7f5aad90390ff3bd466c2cf2f8fed9e6720e89be5ec6a8cff5577e8cb7e1887ac81b18db6f35d216326463a58ef7b47695867de5a95c8500c1934dfb30a2b5253410773c67712d4445560a50b3cd6280ce214924caee276ecc", + "a5b06db251551fbf3e8ddd1992ea1bbd326529a48967b1906800da0da65954f210142f45e03b23fad750ac93e643010a5c78709846a97bf395072ad374b33fa36082394e3448c01cf6c291644d3cf89d359a94e37af0f96eb912b8042d02281385728087db2bf14f26a2e1497e9ccca7b6a0d09b3677ad8b6b4a031d058a064bafe531b5d4c60c66ba83fd090fae71b76fdc41e8178e407f6230ffa88425fb16ce3744ab991eeb183a47f75f81cfed582c6cfe9e57539720ca791a5a88f5699fe7d90ebe42df56e44c22aa730b15c5eefcc7d6cbcd8ce27621e9d1ecc87dd88f617c2ebcdeb475d2c4633da15e5d6a0824c927bbef33865bd5385211f4c396c1", + "345adb2c5957122b30c2a092bfedbc45de279b96d3e6c5ebd8244ba421cca8d6ce3cbab109e0d732664a831d19ca89670f420771e9bb445e8517c4ae9c3f6b78e76d02a7fe33e3d90a7deaf118877b6203795223003e25b9dd16683b1f90a62ac629918a9def1e8476ee4f39fb111b0b93ad49b705e14dcbe838d055f2f70d8b65cdfad49ec9814e14c826b6f9aaf580f86a98ab58f3b88eb5974372a2da64c1405c13b0e5bd089f1c7e8f06be6e501a2f37a1fc102e705304206348e2fd6f7a7561b3353acf5b888251d247a5a9746c31947c9ac0ec150e28012dc3f0b4e48ddcac3d5f86c79522f4b2a35446d1778c0cffaf565d36697f994cd56073df41f6", + "04da79631ebdeae30b652501cda992ed187557308903096adcc798a450911fb10c778566ca121c67c2e01783599dd5228256a89fc66048b311fca328fb06dd5dba297a4fe8fee910cbf3937b6c6954e744a2841d8dcefffa1a879074a1f814aabcc0cf31b4d9bfd85e262dd0e43f19d68c2fab3958726edf3be63cb66288de40b28f9b7c9543d19eac9cd423e10e4b5333462013341b97f7f1c3614a6f5a217f702e554105c5d776e52715ec425c4d78358befd2eeb5beae023ad35fc424f0f9514eeb000ffdaf3ec19a528681807ef62bccb97d68f2ad99a7072c7338b06bb78e71a0f43da60d37db0a473616966d322a5be24594f5a54cc88a4964bb08c9b8" +]; + +function rotate_right(data: Uint8Array, nBytes: number, nBits: number) { + let prior = data[nBytes - 1]; + + for (let i = 0; i < nBytes; i++) { + let current = data[i]; + + data[i] = (current >> nBits) | ((prior & ((1 << nBits) - 1)) << (8 - nBits)); + prior = current; + } +} + +const S_BOX_INV = s_box_inv.map(x => new Uint8Array(Buffer.from(x, 'hex'))); +const N_TABLES = S_BOX_INV.length - 1; +const ITER_ADD = 5; + +export function performDecrypt(data: Uint8Array) { + const spad = data.map(x => S_BOX_INV[N_TABLES][x]); + + let count = (spad[15] >> 4) + 7; + let table = spad[15] + ITER_ADD * count; + + for (let z = 0; z < count; z++) { + table -= ITER_ADD; + rotate_right(spad, 15, 5); + + for (let i = 0; i < 15; i++) { + spad[i] = S_BOX_INV[table % N_TABLES][spad[i]]; + } + } + + return { + version: spad[0], + accessCodeBytes: spad.slice(6) // access code is a binary-coded decimal + }; +} diff --git a/amnet-native/lib/iccard.ts b/amnet-native/lib/iccard.ts new file mode 100644 index 0000000..516baa1 --- /dev/null +++ b/amnet-native/lib/iccard.ts @@ -0,0 +1,133 @@ +import {Buffer} from "buffer"; +import NfcManager, {NfcTech} from "react-native-nfc-manager"; + +import {performDecrypt} from "./iccard-crypto"; + +export enum ICType { + Amusement = 1, + Transport = 2 +} + +export enum AmusementICVendor { + Sega = 0x0078, + Konami = 0x0068, + BandaiNamcoEntertainment = 0x002A, + BandaiNamcoGames = 0x003A, + Nesica = 0x0079, + Unknown = 0x0000 +} + +type AmusementICCard = { + type: ICType.Amusement, + + idm: string, + accessCode: string, + vendor: AmusementICVendor +} + +type TransportICCard = { + type: ICType.Transport, + + idm: string +} + +export type ICCard = AmusementICCard | TransportICCard; + +/** + * Converts an IC card IDm to the 20-digit "0008" number used by some networks + * @param idm The IDm to convert + */ +export function icCard0008Number(idm: string): string { + // 0008 is the numerical representation of the idm padded with zeros until it is 20 digits + return BigInt(`0x${idm}`).toString().padStart(20, '0'); +} + +/** + * Reads a FeliCa card, returning access code information. + */ +export async function felicaCardReadAsync(): Promise { + try { + await NfcManager.requestTechnology(NfcTech.FelicaIOS, { + isReaderModeEnabled: true, + invalidateAfterFirstRead: false, + alertMessage: "Place an Amusement IC or Transport card on your device." + }); + + const tag = await NfcManager.getTag(); + const idm = tag['idm'] as string; + + switch (tag['systemCode'] as string) { + case "0003": + return { + type: ICType.Transport, + idm + }; + + case "88B4": + return await readAmusementICCardContents(idm); + + default: + return null; + } + } catch (ex) { + console.warn(ex); + return null; + } finally { + await NfcManager.cancelTechnologyRequest(); + } +} + +async function readAmusementICCardContents(idm: string): Promise { + const idmBytes = Uint8Array.from(Buffer.from(idm, 'hex')); + const readCommand = [ + 0x06, // read + ...idmBytes, + 0x01, // service count (fixed) + 0x0B, 0x00, // service code (000b, le) + 0x02, // block count + 0x80, 0x00, // S_PAD0 block + 0x80, 0x82 // ID block + ]; + + let response = await NfcManager.sendFelicaCommandIOS(readCommand); + const offset = response.indexOf(0x07); // look for 0x07 as for some reason the response may not start at response[0] + + // response must have 44 bytes + if (offset === -1 || response.length - offset !== 44) { + return null; + } else if (offset !== 0) { + response = response.slice(offset); + } + + // response format: + // 0 - read response (0x07) + // 1-8 - IDm + // 9 - status flag 1 + // 10 - status flag 2 + // 11 - number of blocks (0x02) + // 12-27 - S_PAD0 block + // 28-43 - ID block (DFC is 35-36) + + if (response[9] !== 0x00 || response[11] !== 0x02) { + return null; + } + + const dfcValue = response[37] | (response[36] << 8); + + if (dfcValue in AmusementICVendor && dfcValue !== AmusementICVendor.Unknown) { + const accessCode = performDecrypt(new Uint8Array(response.slice(12, 28))); + return { + type: ICType.Amusement, + accessCode: [...accessCode.accessCodeBytes].map(x => x.toString(16).padStart(2, '0')).join(''), + vendor: dfcValue, + idm + }; + } + + return { + type: ICType.Amusement, + accessCode: icCard0008Number(idm), + vendor: AmusementICVendor.Unknown, + idm + }; +} diff --git a/amnet-native/metro.config.js b/amnet-native/metro.config.js index 492244c..06fa400 100644 --- a/amnet-native/metro.config.js +++ b/amnet-native/metro.config.js @@ -6,7 +6,8 @@ module.exports = (async () => { const config = await getDefaultConfig(__dirname); config.resolver.extraNodeModules = { - 'amnet-shared': resolve(__dirname, '../amnet-shared') + 'amnet-shared': resolve(__dirname, '../amnet-shared'), + '@babel/runtime': resolve(__dirname, 'node_modules/@babel/runtime') }; config.watchFolders = [ diff --git a/amnet-native/models/AMCard.ts b/amnet-native/models/AMCard.ts index 978faba..430eeb1 100644 --- a/amnet-native/models/AMCard.ts +++ b/amnet-native/models/AMCard.ts @@ -1,4 +1,5 @@ import {Realm} from "realm"; +import {AmusementICVendor, ICType} from "../lib/iccard"; export interface AMCardData { code: string; @@ -6,6 +7,7 @@ export interface AMCardData { added: Date; lastUsed?: Date | null; + physicalCardData?: AMPhysicalCardData | null; } export class AMCard extends Realm.Object implements AMCardData { @@ -18,6 +20,8 @@ export class AMCard extends Realm.Object implements AMCardData { lastUsed?: Date; lastUsedGameId?: string | null; + physicalCardData?: AMPhysicalCardData | null = null; + static generate(code: string, name: string) { return { _id: new Realm.BSON.ObjectId(), @@ -27,6 +31,16 @@ export class AMCard extends Realm.Object implements AMCardData { }; } + static delete(realm: Realm, card: AMCard) { + realm.write(() => { + if (card.physicalCardData) { + realm.delete(card.physicalCardData); + } + + realm.delete(card); + }); + } + static schema: Realm.ObjectSchema = { name: "card", primaryKey: "_id", @@ -36,8 +50,32 @@ export class AMCard extends Realm.Object implements AMCardData { code: "string", name: {type: "string", default: "New Card"}, added: {type: "date", default: new Date()}, - lastUsed: {type: "date", optional: true}, - lastUsedGameId: {type: "string", optional: true} + lastUsed: {type: "date", optional: true, indexed: true}, + lastUsedGameId: {type: "string", optional: true, indexed: true}, + physicalCardData: {type: "object", objectType: "physicalCard", optional: true} + } + }; +} + +export class AMPhysicalCardData extends Realm.Object { + + cardIDm: string; + cardType: ICType; + cardVendor: AmusementICVendor | null; + + get isBootlegAmusementCard() { + // real cards have an IDm manufacturer code of 012E (first two bytes of the IDm or in this case, the first 4 characters) + return this.cardType === ICType.Amusement && !this.cardIDm.startsWith("012E"); + } + + static schema: Realm.ObjectSchema = { + name: "physicalCard", + primaryKey: "cardIDm", + + properties: { + cardIDm: "string", + cardType: "int", + cardVendor: {type: "int", optional: true} } }; } \ No newline at end of file diff --git a/amnet-native/models/AMServer.ts b/amnet-native/models/AMServer.ts index 08e5f33..4571dc9 100644 --- a/amnet-native/models/AMServer.ts +++ b/amnet-native/models/AMServer.ts @@ -12,7 +12,9 @@ export class AMServer extends Realm.Object implements AMServerConnecti lastUsed: Date; createdAt: Date; - + + preferredCardIdFormat?: "idm" | "access" | null; + get shareUrl() { return `http://card.ppc.moe/#/servers/add?address=${encodeURIComponent(this.serverAddress)}`; } @@ -40,9 +42,9 @@ export class AMServer extends Realm.Object implements AMServerConnecti apiVersion: {type: "int", default: 0}, gameId: {type: "string", optional: true}, serverAddress: "string", - serverName: {type: "string", default: "New Server"}, + serverName: {type: "string", default: "New Server", indexed: "full-text"}, createdAt: {type: "date", default: new Date()}, - lastUsed: {type: "date", optional: true} + lastUsed: {type: "date", optional: true, indexed: true} } }; } \ No newline at end of file diff --git a/amnet-native/models/RealmContext.ts b/amnet-native/models/RealmContext.ts index 5bd5ecf..6ecd846 100644 --- a/amnet-native/models/RealmContext.ts +++ b/amnet-native/models/RealmContext.ts @@ -1,10 +1,10 @@ import {createRealmContext} from "@realm/react"; -import {AMCard} from "./AMCard"; +import {AMCard, AMPhysicalCardData} from "./AMCard"; import {AMServer} from "./AMServer"; // @ts-ignore export default createRealmContext({ - schemaVersion: 3, - schema: [AMCard, AMServer], + schemaVersion: 4, + schema: [AMPhysicalCardData, AMCard, AMServer], deleteRealmIfMigrationNeeded: false }); \ No newline at end of file diff --git a/amnet-native/package-lock.json b/amnet-native/package-lock.json index 4dd72ff..70893fc 100644 --- a/amnet-native/package-lock.json +++ b/amnet-native/package-lock.json @@ -7,8 +7,8 @@ "": { "name": "amnet-native", "version": "1.1.0", - "hasInstallScript": true, "dependencies": { + "@babel/runtime": "^7.26.0", "@expo-google-fonts/jetbrains-mono": "^0.2.3", "@react-navigation/bottom-tabs": "^6.6.1", "@react-navigation/native": "^6.1.18", @@ -17,26 +17,28 @@ "@types/react": "~18.3.12", "amnet-shared": "file:../amnet-shared", "date-fns": "^3.6.0", - "expo": "^52.0.0", - "expo-blur": "~14.0.1", - "expo-build-properties": "^0.13.1", - "expo-clipboard": "~7.0.0", + "expo": "^52.0.27", + "expo-blur": "~14.0.3", + "expo-build-properties": "~0.13.2", + "expo-clipboard": "~7.0.1", "expo-constants": "~17.0.3", - "expo-dev-client": "~5.0.4", - "expo-linking": "~7.0.3", - "expo-status-bar": "~2.0.0", - "expo-system-ui": "~4.0.4", + "expo-dev-client": "~5.0.10", + "expo-linking": "~7.0.4", + "expo-splash-screen": "~0.29.21", + "expo-status-bar": "~2.0.1", + "expo-system-ui": "~4.0.7", "lucide-react-native": "^0.427.0", - "patch-package": "^8.0.0", + "pusher-js": "^8.2.0", "react": "18.3.1", - "react-native": "0.76.5", + "react-native": "0.76.6", "react-native-context-menu-view": "^1.16.0", "react-native-gesture-handler": "~2.20.2", "react-native-get-random-values": "^1.11.0", + "react-native-nfc-manager": "^3.16.1", "react-native-paper": "^5.12.5", "react-native-reanimated": "~3.16.1", "react-native-safe-area-context": "4.12.0", - "react-native-screens": "~4.1.0", + "react-native-screens": "~4.4.0", "react-native-svg": "15.8.0", "react-native-url-polyfill": "^2.0.0", "realm": "^12.14.0", @@ -45,15 +47,20 @@ }, "../amnet-shared": { "version": "1.0.0", + "dependencies": { + "big-integer": "^1.6.52", + "lodash": "^4.17.21" + }, "devDependencies": { + "@types/lodash": "^4.17.14", "tsup": "^8.2.4", "typescript": "^5.5.4" } }, "node_modules/@0no-co/graphql.web": { - "version": "1.0.12", - "resolved": "https://registry.npmjs.org/@0no-co/graphql.web/-/graphql.web-1.0.12.tgz", - "integrity": "sha512-BTDjjsV/zSPy5fqItwm+KWUfh9CSe9tTtR6rCB72ddtkAxdcHbi4Ir4r/L1Et4lyxmL+i7Rb3m9sjLLi9tYrzA==", + "version": "1.0.13", + "resolved": "https://registry.npmjs.org/@0no-co/graphql.web/-/graphql.web-1.0.13.tgz", + "integrity": "sha512-jqYxOevheVTU1S36ZdzAkJIdvRp2m3OYIG5SEoKDw5NI8eVwkoI0D/Q3DYNGmXCxkA6CQuoa7zvMiDPTLqUNuw==", "license": "MIT", "peerDependencies": { "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0" @@ -131,13 +138,13 @@ } }, "node_modules/@babel/generator": { - "version": "7.26.3", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.26.3.tgz", - "integrity": "sha512-6FF/urZvD0sTeO7k6/B15pMLC4CHUv1426lzr3N01aHJTl046uCAh9LXW/fzeXXjPNCJ6iABW5XaWOsIZB93aQ==", + "version": "7.26.5", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.26.5.tgz", + "integrity": "sha512-2caSP6fN9I7HOe6nqhtft7V4g7/V/gfDsC3Ag4W7kEzzvRGKqiv0pu0HogPiZ3KaVSoNDhUws6IJjDjpfmYIXw==", "license": "MIT", "dependencies": { - "@babel/parser": "^7.26.3", - "@babel/types": "^7.26.3", + "@babel/parser": "^7.26.5", + "@babel/types": "^7.26.5", "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.25", "jsesc": "^3.0.2" @@ -480,12 +487,12 @@ } }, "node_modules/@babel/parser": { - "version": "7.26.3", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.26.3.tgz", - "integrity": "sha512-WJ/CvmY8Mea8iDXo6a7RK2wbmJITT5fN3BEkRuFlxVyNx8jOKIIhmC4fSkTcPcf8JyavbBwIe6OpiCOBXt/IcA==", + "version": "7.26.5", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.26.5.tgz", + "integrity": "sha512-SRJ4jYmXRqV1/Xc+TIVG84WjHBXKlxO9sHQnA2Pf12QQEAp1LOh6kDzNHXcUnbH1QI0FDoPPVOt+vyUDucxpaw==", "license": "MIT", "dependencies": { - "@babel/types": "^7.26.3" + "@babel/types": "^7.26.5" }, "bin": { "parser": "bin/babel-parser.js" @@ -2165,16 +2172,16 @@ }, "node_modules/@babel/traverse--for-generate-function-map": { "name": "@babel/traverse", - "version": "7.26.4", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.26.4.tgz", - "integrity": "sha512-fH+b7Y4p3yqvApJALCPJcwb0/XaOSgtK4pzV6WVjPR5GLFQBRI7pfoX2V2iM48NXvX07NUxxm1Vw98YjqTcU5w==", + "version": "7.26.5", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.26.5.tgz", + "integrity": "sha512-rkOSPOw+AXbgtwUga3U4u8RpoK9FEFWBNAlTpcnkLFjL5CT+oyHNuUUC/xx6XefEJ16r38r8Bc/lfp6rYuHeJQ==", "license": "MIT", "dependencies": { "@babel/code-frame": "^7.26.2", - "@babel/generator": "^7.26.3", - "@babel/parser": "^7.26.3", + "@babel/generator": "^7.26.5", + "@babel/parser": "^7.26.5", "@babel/template": "^7.25.9", - "@babel/types": "^7.26.3", + "@babel/types": "^7.26.5", "debug": "^4.3.1", "globals": "^11.1.0" }, @@ -2183,9 +2190,9 @@ } }, "node_modules/@babel/types": { - "version": "7.26.3", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.26.3.tgz", - "integrity": "sha512-vN5p+1kl59GVKMvTHt55NzzmYVxprfJD+ql7U9NFIfKCBkYE55LYtS+WtPlaYOyzydrKI8Nezd+aZextrd+FMA==", + "version": "7.26.5", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.26.5.tgz", + "integrity": "sha512-L6mZmwFDK6Cjh1nRCLXpa6no13ZIioJDz7mdkzHv399pThrTa/k0nUlNaenOeh2kWu/iaOQYElEpKPUswUa9Vg==", "license": "MIT", "dependencies": { "@babel/helper-string-parser": "^7.25.9", @@ -2248,29 +2255,29 @@ } }, "node_modules/@expo/cli": { - "version": "0.22.5", - "resolved": "https://registry.npmjs.org/@expo/cli/-/cli-0.22.5.tgz", - "integrity": "sha512-A2wYKtcBbEEyRUAyUeMDd356UROo1xaMl7ZaZC5tQOdIhvWKelRd4f3QCaI56D9B4EMWLg9pVuPVbAMz8zJ4+A==", + "version": "0.22.10", + "resolved": "https://registry.npmjs.org/@expo/cli/-/cli-0.22.10.tgz", + "integrity": "sha512-MA4TOtf6x8ixVaQbUINgest/DsrWcMVGMmjXYtnhUfwQGvZtJC+aI+xMBM7ow2OqY2B/xfoRcgqkvWkl36yxkA==", "license": "MIT", "dependencies": { "@0no-co/graphql.web": "^1.0.8", "@babel/runtime": "^7.20.0", "@expo/code-signing-certificates": "^0.0.5", - "@expo/config": "~10.0.4", - "@expo/config-plugins": "~9.0.10", + "@expo/config": "~10.0.8", + "@expo/config-plugins": "~9.0.14", "@expo/devcert": "^1.1.2", - "@expo/env": "~0.4.0", - "@expo/image-utils": "^0.6.0", - "@expo/json-file": "^9.0.0", - "@expo/metro-config": "~0.19.0", - "@expo/osascript": "^2.0.31", - "@expo/package-manager": "^1.5.0", - "@expo/plist": "^0.2.0", - "@expo/prebuild-config": "^8.0.23", + "@expo/env": "~0.4.1", + "@expo/image-utils": "^0.6.4", + "@expo/json-file": "^9.0.1", + "@expo/metro-config": "~0.19.9", + "@expo/osascript": "^2.1.5", + "@expo/package-manager": "^1.7.1", + "@expo/plist": "^0.2.1", + "@expo/prebuild-config": "^8.0.25", "@expo/rudder-sdk-node": "^1.1.1", "@expo/spawn-async": "^1.7.2", "@expo/xcpretty": "^4.3.0", - "@react-native/dev-middleware": "0.76.5", + "@react-native/dev-middleware": "0.76.6", "@urql/core": "^5.0.6", "@urql/exchange-retry": "^1.3.0", "accepts": "^1.3.8", @@ -2309,7 +2316,7 @@ "requireg": "^0.2.2", "resolve": "^1.22.2", "resolve-from": "^5.0.0", - "resolve.exports": "^2.0.2", + "resolve.exports": "^2.0.3", "semver": "^7.6.0", "send": "^0.19.0", "slugify": "^1.3.4", @@ -2352,15 +2359,15 @@ } }, "node_modules/@expo/config": { - "version": "10.0.6", - "resolved": "https://registry.npmjs.org/@expo/config/-/config-10.0.6.tgz", - "integrity": "sha512-xXkfPElrtxznkOZxFASJ7OPa6E9IHSjcZwj5BQ6XUF2dz5M7AFa2h5sXM8AalSaDU5tEBSgoUOjTh5957TlR8g==", + "version": "10.0.8", + "resolved": "https://registry.npmjs.org/@expo/config/-/config-10.0.8.tgz", + "integrity": "sha512-RaKwi8e6PbkMilRexdsxObLMdQwxhY6mlgel+l/eW+IfIw8HEydSU0ERlzYUjlGJxHLHUXe4rC2vw8FEvaowyQ==", "license": "MIT", "dependencies": { "@babel/code-frame": "~7.10.4", - "@expo/config-plugins": "~9.0.10", - "@expo/config-types": "^52.0.0", - "@expo/json-file": "^9.0.0", + "@expo/config-plugins": "~9.0.14", + "@expo/config-types": "^52.0.3", + "@expo/json-file": "^9.0.1", "deepmerge": "^4.3.1", "getenv": "^1.0.0", "glob": "^10.4.2", @@ -2373,14 +2380,14 @@ } }, "node_modules/@expo/config-plugins": { - "version": "9.0.12", - "resolved": "https://registry.npmjs.org/@expo/config-plugins/-/config-plugins-9.0.12.tgz", - "integrity": "sha512-/Ko/NM+GzvJyRkq8PITm8ms0KY5v0wmN1OQFYRMkcJqOi3PjlhndW+G6bHpJI9mkQXBaUnHwAiGLqIC3+MQ5Wg==", + "version": "9.0.14", + "resolved": "https://registry.npmjs.org/@expo/config-plugins/-/config-plugins-9.0.14.tgz", + "integrity": "sha512-Lx1ebV95rTFKKQmbu4wMPLz65rKn7mqSpfANdCx+KwRxuLY2JQls8V4h3lQjG6dW8NWf9qV5QaEFAgNB6VMyOQ==", "license": "MIT", "dependencies": { - "@expo/config-types": "^52.0.0", - "@expo/json-file": "~9.0.0", - "@expo/plist": "^0.2.0", + "@expo/config-types": "^52.0.3", + "@expo/json-file": "~9.0.1", + "@expo/plist": "^0.2.1", "@expo/sdk-runtime-versions": "^1.0.0", "chalk": "^4.1.2", "debug": "^4.3.5", @@ -2407,9 +2414,9 @@ } }, "node_modules/@expo/config-types": { - "version": "52.0.1", - "resolved": "https://registry.npmjs.org/@expo/config-types/-/config-types-52.0.1.tgz", - "integrity": "sha512-vD8ZetyKV7U29lR6+NJohYeoLYTH+eNYXJeNiSOrWCz0witJYY11meMmEnpEaVbN89EfC6uauSUOa6wihtbyPQ==", + "version": "52.0.3", + "resolved": "https://registry.npmjs.org/@expo/config-types/-/config-types-52.0.3.tgz", + "integrity": "sha512-muxvuARmbysH5OGaiBRlh1Y6vfdmL56JtpXxB+y2Hfhu0ezG1U4FjZYBIacthckZPvnDCcP3xIu1R+eTo7/QFA==", "license": "MIT" }, "node_modules/@expo/config/node_modules/@babel/code-frame": { @@ -2463,9 +2470,9 @@ } }, "node_modules/@expo/env": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/@expo/env/-/env-0.4.0.tgz", - "integrity": "sha512-g2JYFqck3xKIwJyK+8LxZ2ENZPWtRgjFWpeht9abnKgzXVXBeSNECFBkg+WQjQocSIdxXhEWM6hz4ZAe7Tc4ng==", + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@expo/env/-/env-0.4.1.tgz", + "integrity": "sha512-oDtbO3i9yXD1nx93acWiPTWGljJ3vABn35x1NAbqtQ2JL6mFOcRcArt1dwi4imZyLnG4VCcjabT9irj+LgYntw==", "license": "MIT", "dependencies": { "chalk": "^4.0.0", @@ -2476,9 +2483,9 @@ } }, "node_modules/@expo/fingerprint": { - "version": "0.11.3", - "resolved": "https://registry.npmjs.org/@expo/fingerprint/-/fingerprint-0.11.3.tgz", - "integrity": "sha512-9lgXmcIePvZ7Wef63XtvuN3HfCUevF4E4tQPdEbH9/dUWwpOvvwQ3KT4OJ9jdh8JJ3nTdO9eDQ/8k8xr1aQ5Kg==", + "version": "0.11.7", + "resolved": "https://registry.npmjs.org/@expo/fingerprint/-/fingerprint-0.11.7.tgz", + "integrity": "sha512-2rfYVS4nqWmOPQk+AL5GPfPSawbqqmI5mL++bxAhWADt+d+fjoQYfIrGtjZxQ30f9o/a1PrRPVSuh2j09+diVg==", "license": "MIT", "dependencies": { "@expo/spawn-async": "^1.7.2", @@ -2509,9 +2516,9 @@ } }, "node_modules/@expo/image-utils": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/@expo/image-utils/-/image-utils-0.6.3.tgz", - "integrity": "sha512-v/JbCKBrHeudxn1gN1TgfPE/pWJSlLPrl29uXJBgrJFQVkViQvUHQNDhaS+UEa9wYI5HHh7XYmtzAehyG4L+GA==", + "version": "0.6.4", + "resolved": "https://registry.npmjs.org/@expo/image-utils/-/image-utils-0.6.4.tgz", + "integrity": "sha512-L++1PBzSvf5iYc6UHJ8Db8GcYNkfLDw+a+zqEFBQ3xqRXP/muxb/O7wuiMFlXrj/cfkx4e0U+z1a4ceV0A7S7Q==", "license": "MIT", "dependencies": { "@expo/spawn-async": "^1.7.2", @@ -2584,9 +2591,9 @@ } }, "node_modules/@expo/json-file": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/@expo/json-file/-/json-file-9.0.0.tgz", - "integrity": "sha512-M+55xFVrFzDcgMDf+52lPDLjKB5xwRfStWlv/b/Vu2OLgxGZLWpxoPYjlRoHqxjPbCQIi2ZCbobK+0KuNhsELg==", + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/@expo/json-file/-/json-file-9.0.1.tgz", + "integrity": "sha512-ZVPhbbEBEwafPCJ0+kI25O2Iivt3XKHEKAADCml1q2cmOIbQnKgLyn8DpOJXqWEyRQr/VWS+hflBh8DU2YFSqg==", "license": "MIT", "dependencies": { "@babel/code-frame": "~7.10.4", @@ -2604,18 +2611,18 @@ } }, "node_modules/@expo/metro-config": { - "version": "0.19.7", - "resolved": "https://registry.npmjs.org/@expo/metro-config/-/metro-config-0.19.7.tgz", - "integrity": "sha512-6Ti05d6AyvXstMpaRGh2EsdGSJzmOh9ju3gMmcjxckn/cimNL39qRQSrnqYc0R/DEZiRFL7N9mVE/0uG668ojw==", + "version": "0.19.9", + "resolved": "https://registry.npmjs.org/@expo/metro-config/-/metro-config-0.19.9.tgz", + "integrity": "sha512-JAsLWhFQqwLH0KsI4OMbPXsKFji5KJEmsi+/02Sz1GCT17YrjRmv1fZ91regUS/FUH2Y/PDAE/+2ulrTgMeG7A==", "license": "MIT", "dependencies": { "@babel/core": "^7.20.0", "@babel/generator": "^7.20.5", "@babel/parser": "^7.20.0", "@babel/types": "^7.20.0", - "@expo/config": "~10.0.4", - "@expo/env": "~0.4.0", - "@expo/json-file": "~9.0.0", + "@expo/config": "~10.0.8", + "@expo/env": "~0.4.1", + "@expo/json-file": "~9.0.1", "@expo/spawn-async": "^1.7.2", "chalk": "^4.1.0", "debug": "^4.3.2", @@ -2666,9 +2673,9 @@ } }, "node_modules/@expo/osascript": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/@expo/osascript/-/osascript-2.1.4.tgz", - "integrity": "sha512-LcPjxJ5FOFpqPORm+5MRLV0CuYWMthJYV6eerF+lQVXKlvgSn3EOqaHC3Vf3H+vmB0f6G4kdvvFtg40vG4bIhA==", + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@expo/osascript/-/osascript-2.1.5.tgz", + "integrity": "sha512-Cp7YF7msGiTAIbFdzNovwHBfecdMLVL5XzSqq4xQz72ALFCQ3uSIUXRph1QV2r61ugH7Yem0gY8yi7RcDlI4qg==", "license": "MIT", "dependencies": { "@expo/spawn-async": "^1.7.2", @@ -2679,12 +2686,12 @@ } }, "node_modules/@expo/package-manager": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/@expo/package-manager/-/package-manager-1.6.1.tgz", - "integrity": "sha512-4rT46wP/94Ll+CWXtFKok1Lbo9XncSUtErFOo/9/3FVughGbIfdG4SKZOAWIpr9wxwEfkyhHfAP9q71ONlWODw==", + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/@expo/package-manager/-/package-manager-1.7.1.tgz", + "integrity": "sha512-DKbELrTOdl7U3KT0C07Aka9P+sUP3LL+1UTKf1KmLx2x2gPH1IC+c68N7iQlwNt+yA37qIw6/vKoqyTGu5EL9g==", "license": "MIT", "dependencies": { - "@expo/json-file": "^9.0.0", + "@expo/json-file": "^9.0.1", "@expo/spawn-async": "^1.7.2", "ansi-regex": "^5.0.0", "chalk": "^4.0.0", @@ -2702,12 +2709,13 @@ "version": "9.1.1", "resolved": "https://registry.npmjs.org/sudo-prompt/-/sudo-prompt-9.1.1.tgz", "integrity": "sha512-es33J1g2HjMpyAhz8lOR+ICmXXAqTuKbuXuUWLhOLew20oN9oUCgCJx615U/v7aioZg7IX5lIh9x34vwneu4pA==", + "deprecated": "Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.", "license": "MIT" }, "node_modules/@expo/plist": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/@expo/plist/-/plist-0.2.0.tgz", - "integrity": "sha512-F/IZJQaf8OIVnVA6XWUeMPC3OH6MV00Wxf0WC0JhTQht2QgjyHUa3U5Gs3vRtDq8tXNsZneOQRDVwpaOnd4zTQ==", + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/@expo/plist/-/plist-0.2.1.tgz", + "integrity": "sha512-9TaXGuNxa0LQwHQn4rYiU6YaERv6dPnQgsdKWq2rKKTr6LWOtGNQCi/yOk/HBLeZSxBm59APT5/6x60uRvr0Mg==", "license": "MIT", "dependencies": { "@xmldom/xmldom": "~0.7.7", @@ -2716,17 +2724,17 @@ } }, "node_modules/@expo/prebuild-config": { - "version": "8.0.23", - "resolved": "https://registry.npmjs.org/@expo/prebuild-config/-/prebuild-config-8.0.23.tgz", - "integrity": "sha512-Zf01kFiN2PISmLb0DhIAJh76v3J2oYUKSjiAtGZLOH0HUz59by/qdyU4mGHWdeyRdCCrLUA21Rct2MBykvRMsg==", + "version": "8.0.25", + "resolved": "https://registry.npmjs.org/@expo/prebuild-config/-/prebuild-config-8.0.25.tgz", + "integrity": "sha512-xYHV8eiydZEDedf2AGaOFRFwcGlaSzrqQH94dwX42urNCU03FO0RUb7yPp4nkb7WNFg5Ov6PDsV7ES+YwzNgYQ==", "license": "MIT", "dependencies": { - "@expo/config": "~10.0.4", - "@expo/config-plugins": "~9.0.10", - "@expo/config-types": "^52.0.0", - "@expo/image-utils": "^0.6.0", - "@expo/json-file": "^9.0.0", - "@react-native/normalize-colors": "0.76.5", + "@expo/config": "~10.0.8", + "@expo/config-plugins": "~9.0.14", + "@expo/config-types": "^52.0.3", + "@expo/image-utils": "^0.6.4", + "@expo/json-file": "^9.0.1", + "@react-native/normalize-colors": "0.76.6", "debug": "^4.3.1", "fs-extra": "^9.0.0", "resolve-from": "^5.0.0", @@ -3247,30 +3255,30 @@ } }, "node_modules/@react-native/assets-registry": { - "version": "0.76.5", - "resolved": "https://registry.npmjs.org/@react-native/assets-registry/-/assets-registry-0.76.5.tgz", - "integrity": "sha512-MN5dasWo37MirVcKWuysRkRr4BjNc81SXwUtJYstwbn8oEkfnwR9DaqdDTo/hHOnTdhafffLIa2xOOHcjDIGEw==", + "version": "0.76.6", + "resolved": "https://registry.npmjs.org/@react-native/assets-registry/-/assets-registry-0.76.6.tgz", + "integrity": "sha512-YI8HoReYiIwdFQs+k9Q9qpFTnsyYikZxgs/UVtVbhKixXDQF6F9LLvj2naOx4cfV+RGybNKxwmDl1vUok/dRFQ==", "license": "MIT", "engines": { "node": ">=18" } }, "node_modules/@react-native/babel-plugin-codegen": { - "version": "0.76.5", - "resolved": "https://registry.npmjs.org/@react-native/babel-plugin-codegen/-/babel-plugin-codegen-0.76.5.tgz", - "integrity": "sha512-xe7HSQGop4bnOLMaXt0aU+rIatMNEQbz242SDl8V9vx5oOTI0VbZV9yLy6yBc6poUlYbcboF20YVjoRsxX4yww==", + "version": "0.76.6", + "resolved": "https://registry.npmjs.org/@react-native/babel-plugin-codegen/-/babel-plugin-codegen-0.76.6.tgz", + "integrity": "sha512-yFC9I/aDBOBz3ZMlqKn2NY/mDUtCksUNZ7AQmBiTAeVTUP0ujEjE0hTOx5Qd+kok7A7hwZEX87HdSgjiJZfr5g==", "license": "MIT", "dependencies": { - "@react-native/codegen": "0.76.5" + "@react-native/codegen": "0.76.6" }, "engines": { "node": ">=18" } }, "node_modules/@react-native/babel-preset": { - "version": "0.76.5", - "resolved": "https://registry.npmjs.org/@react-native/babel-preset/-/babel-preset-0.76.5.tgz", - "integrity": "sha512-1Nu5Um4EogOdppBLI4pfupkteTjWfmI0hqW8ezWTg7Bezw0FtBj8yS8UYVd3wTnDFT9A5mA2VNoNUqomJnvj2A==", + "version": "0.76.6", + "resolved": "https://registry.npmjs.org/@react-native/babel-preset/-/babel-preset-0.76.6.tgz", + "integrity": "sha512-ojlVWY6S/VE/nb9hIRetPMTsW9ZmGb2R3dnToEXAtQQDz41eHMHXbkw/k2h0THp6qhas25ruNvn3N5n2o+lBzg==", "license": "MIT", "dependencies": { "@babel/core": "^7.25.2", @@ -3314,7 +3322,7 @@ "@babel/plugin-transform-typescript": "^7.25.2", "@babel/plugin-transform-unicode-regex": "^7.24.7", "@babel/template": "^7.25.0", - "@react-native/babel-plugin-codegen": "0.76.5", + "@react-native/babel-plugin-codegen": "0.76.6", "babel-plugin-syntax-hermes-parser": "^0.25.1", "babel-plugin-transform-flow-enums": "^0.0.2", "react-refresh": "^0.14.0" @@ -3327,9 +3335,9 @@ } }, "node_modules/@react-native/codegen": { - "version": "0.76.5", - "resolved": "https://registry.npmjs.org/@react-native/codegen/-/codegen-0.76.5.tgz", - "integrity": "sha512-FoZ9VRQ5MpgtDAnVo1rT9nNRfjnWpE40o1GeJSDlpUMttd36bVXvsDm8W/NhX8BKTWXSX+CPQJsRcvN1UPYGKg==", + "version": "0.76.6", + "resolved": "https://registry.npmjs.org/@react-native/codegen/-/codegen-0.76.6.tgz", + "integrity": "sha512-BABb3e5G/+hyQYEYi0AODWh2km2d8ERoASZr6Hv90pVXdUHRYR+yxCatX7vSd9rnDUYndqRTzD0hZWAucPNAKg==", "license": "MIT", "dependencies": { "@babel/parser": "^7.25.3", @@ -3370,13 +3378,13 @@ } }, "node_modules/@react-native/community-cli-plugin": { - "version": "0.76.5", - "resolved": "https://registry.npmjs.org/@react-native/community-cli-plugin/-/community-cli-plugin-0.76.5.tgz", - "integrity": "sha512-3MKMnlU0cZOWlMhz5UG6WqACJiWUrE3XwBEumzbMmZw3Iw3h+fIsn+7kLLE5EhzqLt0hg5Y4cgYFi4kOaNgq+g==", + "version": "0.76.6", + "resolved": "https://registry.npmjs.org/@react-native/community-cli-plugin/-/community-cli-plugin-0.76.6.tgz", + "integrity": "sha512-nETlc/+U5cESVluzzgN0OcVfcoMijGBaDWzOaJhoYUodcuqnqtu75XsSEc7yzlYjwNQG+vF83mu9CQGezruNMA==", "license": "MIT", "dependencies": { - "@react-native/dev-middleware": "0.76.5", - "@react-native/metro-babel-transformer": "0.76.5", + "@react-native/dev-middleware": "0.76.6", + "@react-native/metro-babel-transformer": "0.76.6", "chalk": "^4.0.0", "execa": "^5.1.1", "invariant": "^2.2.4", @@ -3501,22 +3509,22 @@ "license": "ISC" }, "node_modules/@react-native/debugger-frontend": { - "version": "0.76.5", - "resolved": "https://registry.npmjs.org/@react-native/debugger-frontend/-/debugger-frontend-0.76.5.tgz", - "integrity": "sha512-5gtsLfBaSoa9WP8ToDb/8NnDBLZjv4sybQQj7rDKytKOdsXm3Pr2y4D7x7GQQtP1ZQRqzU0X0OZrhRz9xNnOqA==", + "version": "0.76.6", + "resolved": "https://registry.npmjs.org/@react-native/debugger-frontend/-/debugger-frontend-0.76.6.tgz", + "integrity": "sha512-kP97xMQjiANi5/lmf8MakS7d8FTJl+BqYHQMqyvNiY+eeWyKnhqW2GL2v3eEUBAuyPBgJGivuuO4RvjZujduJg==", "license": "BSD-3-Clause", "engines": { "node": ">=18" } }, "node_modules/@react-native/dev-middleware": { - "version": "0.76.5", - "resolved": "https://registry.npmjs.org/@react-native/dev-middleware/-/dev-middleware-0.76.5.tgz", - "integrity": "sha512-f8eimsxpkvMgJia7POKoUu9uqjGF6KgkxX4zqr/a6eoR1qdEAWUd6PonSAqtag3PAqvEaJpB99gLH2ZJI1nDGg==", + "version": "0.76.6", + "resolved": "https://registry.npmjs.org/@react-native/dev-middleware/-/dev-middleware-0.76.6.tgz", + "integrity": "sha512-1bAyd2/X48Nzb45s5l2omM75vy764odx/UnDs4sJfFCuK+cupU4nRPgl0XWIqgdM/2+fbQ3E4QsVS/WIKTFxvQ==", "license": "MIT", "dependencies": { "@isaacs/ttlcache": "^1.4.1", - "@react-native/debugger-frontend": "0.76.5", + "@react-native/debugger-frontend": "0.76.6", "chrome-launcher": "^0.15.2", "chromium-edge-launcher": "^0.2.0", "connect": "^3.6.5", @@ -3556,31 +3564,31 @@ } }, "node_modules/@react-native/gradle-plugin": { - "version": "0.76.5", - "resolved": "https://registry.npmjs.org/@react-native/gradle-plugin/-/gradle-plugin-0.76.5.tgz", - "integrity": "sha512-7KSyD0g0KhbngITduC8OABn0MAlJfwjIdze7nA4Oe1q3R7qmAv+wQzW+UEXvPah8m1WqFjYTkQwz/4mK3XrQGw==", + "version": "0.76.6", + "resolved": "https://registry.npmjs.org/@react-native/gradle-plugin/-/gradle-plugin-0.76.6.tgz", + "integrity": "sha512-sDzpf4eiynryoS6bpYCweGoxSmWgCSx9lzBoxIIW+S6siyGiTaffzZHWCm8mIn9UZsSPlEO37q62ggnR9Zu/OA==", "license": "MIT", "engines": { "node": ">=18" } }, "node_modules/@react-native/js-polyfills": { - "version": "0.76.5", - "resolved": "https://registry.npmjs.org/@react-native/js-polyfills/-/js-polyfills-0.76.5.tgz", - "integrity": "sha512-ggM8tcKTcaqyKQcXMIvcB0vVfqr9ZRhWVxWIdiFO1mPvJyS6n+a+lLGkgQAyO8pfH0R1qw6K9D0nqbbDo865WQ==", + "version": "0.76.6", + "resolved": "https://registry.npmjs.org/@react-native/js-polyfills/-/js-polyfills-0.76.6.tgz", + "integrity": "sha512-cDD7FynxWYxHkErZzAJtzPGhJ13JdOgL+R0riTh0hCovOfIUz9ItffdLQv2nx48lnvMTQ+HZXMnGOZnsFCNzQw==", "license": "MIT", "engines": { "node": ">=18" } }, "node_modules/@react-native/metro-babel-transformer": { - "version": "0.76.5", - "resolved": "https://registry.npmjs.org/@react-native/metro-babel-transformer/-/metro-babel-transformer-0.76.5.tgz", - "integrity": "sha512-Cm9G5Sg5BDty3/MKa3vbCAJtT3YHhlEaPlQALLykju7qBS+pHZV9bE9hocfyyvc5N/osTIGWxG5YOfqTeMu1oQ==", + "version": "0.76.6", + "resolved": "https://registry.npmjs.org/@react-native/metro-babel-transformer/-/metro-babel-transformer-0.76.6.tgz", + "integrity": "sha512-xSBi9jPliThu5HRSJvluqUlDOLLEmf34zY/U7RDDjEbZqC0ufPcPS7c5XsSg0GDPiXc7lgjBVesPZsKFkoIBgA==", "license": "MIT", "dependencies": { "@babel/core": "^7.25.2", - "@react-native/babel-preset": "0.76.5", + "@react-native/babel-preset": "0.76.6", "hermes-parser": "0.23.1", "nullthrows": "^1.1.1" }, @@ -3592,15 +3600,15 @@ } }, "node_modules/@react-native/normalize-colors": { - "version": "0.76.5", - "resolved": "https://registry.npmjs.org/@react-native/normalize-colors/-/normalize-colors-0.76.5.tgz", - "integrity": "sha512-6QRLEok1r55gLqj+94mEWUENuU5A6wsr2OoXpyq/CgQ7THWowbHtru/kRGRr6o3AQXrVnZheR60JNgFcpNYIug==", + "version": "0.76.6", + "resolved": "https://registry.npmjs.org/@react-native/normalize-colors/-/normalize-colors-0.76.6.tgz", + "integrity": "sha512-1n4udXH2Cla31iA/8eLRdhFHpYUYK1NKWCn4m1Sr9L4SarWKAYuRFliK1fcLvPPALCFoFlWvn8I0ekdUOHMzDQ==", "license": "MIT" }, "node_modules/@react-native/virtualized-lists": { - "version": "0.76.5", - "resolved": "https://registry.npmjs.org/@react-native/virtualized-lists/-/virtualized-lists-0.76.5.tgz", - "integrity": "sha512-M/fW1fTwxrHbcx0OiVOIxzG6rKC0j9cR9Csf80o77y1Xry0yrNPpAlf8D1ev3LvHsiAUiRNFlauoPtodrs2J1A==", + "version": "0.76.6", + "resolved": "https://registry.npmjs.org/@react-native/virtualized-lists/-/virtualized-lists-0.76.6.tgz", + "integrity": "sha512-0HUWVwJbRq1BWFOu11eOWGTSmK9nMHhoMPyoI27wyWcl/nqUx7HOxMbRVq0DsTCyATSMPeF+vZ6o1REapcNWKw==", "license": "MIT", "dependencies": { "invariant": "^2.2.4", @@ -3935,12 +3943,6 @@ "node": ">=10.0.0" } }, - "node_modules/@yarnpkg/lockfile": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@yarnpkg/lockfile/-/lockfile-1.1.0.tgz", - "integrity": "sha512-GpSwvyXOcOOlV70vbnzjj4fW5xW/FdUF6nQEt1ENy7m4ZCczi1+/buVUPAqmGfqznsORNFzUMjctTIp8a9tuCQ==", - "license": "BSD-2-Clause" - }, "node_modules/abort-controller": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", @@ -4322,9 +4324,9 @@ } }, "node_modules/babel-preset-expo": { - "version": "12.0.4", - "resolved": "https://registry.npmjs.org/babel-preset-expo/-/babel-preset-expo-12.0.4.tgz", - "integrity": "sha512-SAzAwqpyjA+/OFrU95OOioj6oTeCv4+rRfrNmBTy5S/gJswrZKBSPJioFudIaJBy43W+BL7HA5AspBIF6tO/aA==", + "version": "12.0.6", + "resolved": "https://registry.npmjs.org/babel-preset-expo/-/babel-preset-expo-12.0.6.tgz", + "integrity": "sha512-az3H7gDVo0wxNBAFES8h5vLLWE8NPGkD9g5P962hDEOqZUdyPacb9MOzicypeLmcq9zQWr6E3iVtEHoNagCTTQ==", "license": "MIT", "dependencies": { "@babel/plugin-proposal-decorators": "^7.12.9", @@ -4333,7 +4335,7 @@ "@babel/plugin-transform-parameters": "^7.22.15", "@babel/preset-react": "^7.22.15", "@babel/preset-typescript": "^7.23.0", - "@react-native/babel-preset": "0.76.5", + "@react-native/babel-preset": "0.76.6", "babel-plugin-react-native-web": "~0.19.13", "react-refresh": "^0.14.2" }, @@ -4633,37 +4635,6 @@ "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", "license": "ISC" }, - "node_modules/call-bind": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.8.tgz", - "integrity": "sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww==", - "license": "MIT", - "dependencies": { - "call-bind-apply-helpers": "^1.0.0", - "es-define-property": "^1.0.0", - "get-intrinsic": "^1.2.4", - "set-function-length": "^1.2.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/call-bind-apply-helpers": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.1.tgz", - "integrity": "sha512-BhYE+WDaywFg2TBWYNXAE+8B1ATnThNBqXHP5nQu0jWJdVvY2hvkpyB3qOmtmDePiS5/BDQ8wASEWGMWRG148g==", - "license": "MIT", - "dependencies": { - "es-errors": "^1.3.0", - "function-bind": "^1.1.2" - }, - "engines": { - "node": ">= 0.4" - } - }, "node_modules/caller-callsite": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/caller-callsite/-/caller-callsite-2.0.0.tgz", @@ -5325,23 +5296,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/define-data-property": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", - "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", - "license": "MIT", - "dependencies": { - "es-define-property": "^1.0.0", - "es-errors": "^1.3.0", - "gopd": "^1.0.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/define-lazy-prop": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz", @@ -5513,20 +5467,6 @@ "url": "https://dotenvx.com" } }, - "node_modules/dunder-proto": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.0.tgz", - "integrity": "sha512-9+Sj30DIu+4KvHqMfLUGLFYL2PkURSYMVXJyXe92nFRvlYq5hBjLEhblKB+vkd/WVlUYMWigiY07T91Fkk0+4A==", - "license": "MIT", - "dependencies": { - "call-bind-apply-helpers": "^1.0.0", - "es-errors": "^1.3.0", - "gopd": "^1.2.0" - }, - "engines": { - "node": ">= 0.4" - } - }, "node_modules/eastasianwidth": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", @@ -5614,36 +5554,6 @@ "stackframe": "^1.3.4" } }, - "node_modules/es-define-property": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", - "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", - "license": "MIT", - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/es-errors": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", - "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", - "license": "MIT", - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/es-object-atoms": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.0.0.tgz", - "integrity": "sha512-MZ4iQ6JwHOBQjahnjwaC1ZtIBH+2ohjamzAO3oaHcXYup7qxjF2fixyH+Q71voWHeOkI2q/TnJao/KfXYIZWbw==", - "license": "MIT", - "dependencies": { - "es-errors": "^1.3.0" - }, - "engines": { - "node": ">= 0.4" - } - }, "node_modules/escalade": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", @@ -5819,26 +5729,26 @@ } }, "node_modules/expo": { - "version": "52.0.18", - "resolved": "https://registry.npmjs.org/expo/-/expo-52.0.18.tgz", - "integrity": "sha512-z+qdUbH0d5JRknE3VrY0s5k+3j5JpsLx4vXRwV4To8Xm5uf3d642FQ2HbuPWFAAhtSKFQsxQAh3iuAUGAWDBhg==", + "version": "52.0.27", + "resolved": "https://registry.npmjs.org/expo/-/expo-52.0.27.tgz", + "integrity": "sha512-PxIS8JRTegUNYq4vNeP0eCqm7p17oGNYjJ/9x207zkwVlklywD9LYIckGojXEY5JPW/DwhbhtO6E2hMgdQQugg==", "license": "MIT", "dependencies": { "@babel/runtime": "^7.20.0", - "@expo/cli": "0.22.5", - "@expo/config": "~10.0.6", - "@expo/config-plugins": "~9.0.12", - "@expo/fingerprint": "0.11.3", - "@expo/metro-config": "0.19.7", + "@expo/cli": "0.22.10", + "@expo/config": "~10.0.8", + "@expo/config-plugins": "~9.0.14", + "@expo/fingerprint": "0.11.7", + "@expo/metro-config": "0.19.9", "@expo/vector-icons": "^14.0.0", - "babel-preset-expo": "~12.0.4", - "expo-asset": "~11.0.1", - "expo-constants": "~17.0.3", - "expo-file-system": "~18.0.5", - "expo-font": "~13.0.1", - "expo-keep-awake": "~14.0.1", - "expo-modules-autolinking": "2.0.4", - "expo-modules-core": "2.1.1", + "babel-preset-expo": "~12.0.6", + "expo-asset": "~11.0.2", + "expo-constants": "~17.0.4", + "expo-file-system": "~18.0.7", + "expo-font": "~13.0.3", + "expo-keep-awake": "~14.0.2", + "expo-modules-autolinking": "2.0.7", + "expo-modules-core": "2.1.4", "fbemitter": "^3.0.0", "web-streams-polyfill": "^3.3.2", "whatwg-url-without-unicode": "8.0.0-3" @@ -5866,13 +5776,13 @@ } }, "node_modules/expo-asset": { - "version": "11.0.1", - "resolved": "https://registry.npmjs.org/expo-asset/-/expo-asset-11.0.1.tgz", - "integrity": "sha512-WatvD7JVC89EsllXFYcS/rji3ajVzE2B/USo0TqedsETixwyVCQfrrvCdCPQyuKghrxVNEj8bQ/Qbea/RZLYjg==", + "version": "11.0.2", + "resolved": "https://registry.npmjs.org/expo-asset/-/expo-asset-11.0.2.tgz", + "integrity": "sha512-We3Td5WsNsNQyXoheLnuwic6JCOt/pqXqIIyWaZ3z/PeHrA+SwoQdI18MjDhkudLK08tbIVyDSUW8IJHXa04eg==", "license": "MIT", "dependencies": { - "@expo/image-utils": "^0.6.0", - "expo-constants": "~17.0.0", + "@expo/image-utils": "^0.6.4", + "expo-constants": "~17.0.4", "invariant": "^2.2.4", "md5-file": "^3.2.3" }, @@ -5883,9 +5793,9 @@ } }, "node_modules/expo-blur": { - "version": "14.0.1", - "resolved": "https://registry.npmjs.org/expo-blur/-/expo-blur-14.0.1.tgz", - "integrity": "sha512-3Q6jFBLbY8n2vwk28ycUC+eIlVhnlqwkXUKk/Lfaj+SGV3AZMQyrixe7OYwJdUfwqETBrnYYMB6uNrJzOSbG+g==", + "version": "14.0.3", + "resolved": "https://registry.npmjs.org/expo-blur/-/expo-blur-14.0.3.tgz", + "integrity": "sha512-BL3xnqBJbYm3Hg9t/HjNjdeY7N/q8eK5tsLYxswWG1yElISWZmMvrXYekl7XaVCPfyFyz8vQeaxd7q74ZY3Wrw==", "license": "MIT", "peerDependencies": { "expo": "*", @@ -5894,9 +5804,9 @@ } }, "node_modules/expo-build-properties": { - "version": "0.13.1", - "resolved": "https://registry.npmjs.org/expo-build-properties/-/expo-build-properties-0.13.1.tgz", - "integrity": "sha512-7tDlAM0PPkXC0B00C6/FG19sMzwxZNyiDfn22AWVbBxWxZE1/3RqxPgT3MlPVNfvy+wJw7jt/qbAb0S06wFYVg==", + "version": "0.13.2", + "resolved": "https://registry.npmjs.org/expo-build-properties/-/expo-build-properties-0.13.2.tgz", + "integrity": "sha512-ML2GwBgn0Bo4yPgnSGb7h3XVxCigS/KFdid3xPC2HldEioTP3UewB/2Qa4WBsam9Fb7lAuRyVHAfRoA3swpDzg==", "license": "MIT", "dependencies": { "ajv": "^8.11.0", @@ -5919,9 +5829,9 @@ } }, "node_modules/expo-clipboard": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/expo-clipboard/-/expo-clipboard-7.0.0.tgz", - "integrity": "sha512-4Vuv1zZPTOiKzIeC0BIGUN8nyzkXlE6jKchtLxcoksBjHPdG5W2eH05B+hppTrK9N3+Xh02z4j3h1cFRqPJ1fw==", + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/expo-clipboard/-/expo-clipboard-7.0.1.tgz", + "integrity": "sha512-rqYk0+WoqitPcPKxmMxSpLonX1E5Ije3LBYfnYMbH3xU5Gr8EAH9QnOWOi4BgahUPvcot6nbFEnx+DqARrmxKQ==", "license": "MIT", "peerDependencies": { "expo": "*", @@ -5930,13 +5840,13 @@ } }, "node_modules/expo-constants": { - "version": "17.0.3", - "resolved": "https://registry.npmjs.org/expo-constants/-/expo-constants-17.0.3.tgz", - "integrity": "sha512-lnbcX2sAu8SucHXEXxSkhiEpqH+jGrf+TF+MO6sHWIESjwOUVVYlT8qYdjR9xbxWmqFtrI4KV44FkeJf2DaFjQ==", + "version": "17.0.4", + "resolved": "https://registry.npmjs.org/expo-constants/-/expo-constants-17.0.4.tgz", + "integrity": "sha512-5c0VlZycmDyQUCMCr3Na3cpHAsVJJ+5o6KkkD4rmATQZ0++Xp/S2gpnjWyEo2riRmO91vxoyHwmAySXuktJddQ==", "license": "MIT", "dependencies": { - "@expo/config": "~10.0.4", - "@expo/env": "~0.4.0" + "@expo/config": "~10.0.8", + "@expo/env": "~0.4.1" }, "peerDependencies": { "expo": "*", @@ -5944,15 +5854,15 @@ } }, "node_modules/expo-dev-client": { - "version": "5.0.6", - "resolved": "https://registry.npmjs.org/expo-dev-client/-/expo-dev-client-5.0.6.tgz", - "integrity": "sha512-UMrS21EQ5TMooQgLp+0YrH+UKpxvO+SzkrAdWyVTrjUJ1Qi1yQCbtcErXkYbAdLbItSF3H04fVvd0lzg0KL3Wg==", + "version": "5.0.10", + "resolved": "https://registry.npmjs.org/expo-dev-client/-/expo-dev-client-5.0.10.tgz", + "integrity": "sha512-iCrpt4XOQjTWbsqlZQSG3wOHsAyboJNg9xpHWBKJy3JFC2uCPH36cX2NvkmEtWqWKXKUjrx0t4B/X9blcDnvSQ==", "license": "MIT", "dependencies": { - "expo-dev-launcher": "5.0.19", - "expo-dev-menu": "6.0.14", - "expo-dev-menu-interface": "1.9.2", - "expo-manifests": "~0.15.0", + "expo-dev-launcher": "5.0.25", + "expo-dev-menu": "6.0.18", + "expo-dev-menu-interface": "1.9.3", + "expo-manifests": "~0.15.5", "expo-updates-interface": "~1.0.0" }, "peerDependencies": { @@ -5960,14 +5870,14 @@ } }, "node_modules/expo-dev-launcher": { - "version": "5.0.19", - "resolved": "https://registry.npmjs.org/expo-dev-launcher/-/expo-dev-launcher-5.0.19.tgz", - "integrity": "sha512-3zlOxpWVuV1RDe8OKoejL7XhzidHvtg3iEw564dhXePH5J+Ha9Owkqqiz7A27iqQrENjU/XWBtOxHszj+OBk4Q==", + "version": "5.0.25", + "resolved": "https://registry.npmjs.org/expo-dev-launcher/-/expo-dev-launcher-5.0.25.tgz", + "integrity": "sha512-5iH89otFs2lFEXMFRXg5E+YMC1wxoZCp2FuemzLPuNtNC8HX64hUy+PeU8F4H8Xc17K6Hd6zAp9QJqgX4l4eMQ==", "license": "MIT", "dependencies": { "ajv": "8.11.0", - "expo-dev-menu": "6.0.14", - "expo-manifests": "~0.15.0", + "expo-dev-menu": "6.0.18", + "expo-manifests": "~0.15.5", "resolve-from": "^5.0.0" }, "peerDependencies": { @@ -5991,30 +5901,30 @@ } }, "node_modules/expo-dev-menu": { - "version": "6.0.14", - "resolved": "https://registry.npmjs.org/expo-dev-menu/-/expo-dev-menu-6.0.14.tgz", - "integrity": "sha512-bG4NXm4epHSmZdWW9hZCS7dTcKO82CyVfYMbNSOw5o/FKO9cY/AgfSj6ERPE9zBqYEJJEJaoJ0mzv0d47/h23g==", + "version": "6.0.18", + "resolved": "https://registry.npmjs.org/expo-dev-menu/-/expo-dev-menu-6.0.18.tgz", + "integrity": "sha512-QexBMNbZR/J3nNF7UaUs7PcY77bTjLSXWHFTuRM17bGlNCBJWfmoSdKSJ0YQtOTx560bJpCdtWJAn0DR2rj3TA==", "license": "MIT", "dependencies": { - "expo-dev-menu-interface": "1.9.2" + "expo-dev-menu-interface": "1.9.3" }, "peerDependencies": { "expo": "*" } }, "node_modules/expo-dev-menu-interface": { - "version": "1.9.2", - "resolved": "https://registry.npmjs.org/expo-dev-menu-interface/-/expo-dev-menu-interface-1.9.2.tgz", - "integrity": "sha512-9piGiHZYnNjoO9oQFWlVsndQ1jhTdGCKf81WfCMHbQBamna/zucC1A+jbGpyzE4icXZZ29CpsSd4uVR+tB2Rfw==", + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/expo-dev-menu-interface/-/expo-dev-menu-interface-1.9.3.tgz", + "integrity": "sha512-KY/dWTBE1l47i9V366JN5rC6YIdOc9hz8yAmZzkl5DrPia5l3M2WIjtnpHC9zUkNjiSiG2urYoOAq4H/uLdmyg==", "license": "MIT", "peerDependencies": { "expo": "*" } }, "node_modules/expo-file-system": { - "version": "18.0.5", - "resolved": "https://registry.npmjs.org/expo-file-system/-/expo-file-system-18.0.5.tgz", - "integrity": "sha512-vm7gA+PB7j99hfvBBFMRiti8OeazFK3AZWtDmCi6WQCXDxngXkAJViXhkHyF3xwDKljzlP8+4BIGrKCzbfoObg==", + "version": "18.0.7", + "resolved": "https://registry.npmjs.org/expo-file-system/-/expo-file-system-18.0.7.tgz", + "integrity": "sha512-6PpbQfogMXdzOsJzlJayy5qf40IfIHhudtAOzr32RlRYL4Hkmk3YcR9jG0PWQ0rklJfAhbAdP63yOcN+wDgzaA==", "license": "MIT", "dependencies": { "web-streams-polyfill": "^3.3.2" @@ -6025,9 +5935,9 @@ } }, "node_modules/expo-font": { - "version": "13.0.1", - "resolved": "https://registry.npmjs.org/expo-font/-/expo-font-13.0.1.tgz", - "integrity": "sha512-8JE47B+6cLeKWr5ql8gU6YsPHjhrz1vMrTqYMm72No/8iW8Sb/uL4Oc0dpmbjq3hLLXBY0xPBQOgU7FQ6Y04Vg==", + "version": "13.0.3", + "resolved": "https://registry.npmjs.org/expo-font/-/expo-font-13.0.3.tgz", + "integrity": "sha512-9IdYz+A+b3KvuCYP7DUUXF4VMZjPU+IsvAnLSVJ2TfP6zUD2JjZFx3jeo/cxWRkYk/aLj5+53Te7elTAScNl4Q==", "license": "MIT", "dependencies": { "fontfaceobserver": "^2.1.0" @@ -6044,9 +5954,9 @@ "license": "MIT" }, "node_modules/expo-keep-awake": { - "version": "14.0.1", - "resolved": "https://registry.npmjs.org/expo-keep-awake/-/expo-keep-awake-14.0.1.tgz", - "integrity": "sha512-c5mGCAIk2YM+Vsdy90BlEJ4ZX+KG5Au9EkJUIxXWlpnuKmDAJ3N+5nEZ7EUO1ZTheqoSBeAo4jJ8rTWPU+JXdw==", + "version": "14.0.2", + "resolved": "https://registry.npmjs.org/expo-keep-awake/-/expo-keep-awake-14.0.2.tgz", + "integrity": "sha512-71XAMnoWjKZrN8J7Q3+u0l9Ytp4OfhNAYz8BCWF1/9aFUw09J3I7Z5DuI3MUsVMa/KWi+XhG+eDUFP8cVA19Uw==", "license": "MIT", "peerDependencies": { "expo": "*", @@ -6054,12 +5964,12 @@ } }, "node_modules/expo-linking": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/expo-linking/-/expo-linking-7.0.3.tgz", - "integrity": "sha512-YiDacNzeQZd/bdOwGyi+YlawM4GGbcSRkuFCpDGIK7D1KUGqLinBHwJvxUMb9Zert2Ois5IHtmZaZ1et6g229g==", + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/expo-linking/-/expo-linking-7.0.4.tgz", + "integrity": "sha512-i+QaFc2zwOoq/ajePVWC+op3cOKC6nd6Wj/BJtukU71byTAbxDhbi+3m0ZFbh2i1/v/iIXRqrl3PvQcKNklPkw==", "license": "MIT", "dependencies": { - "expo-constants": "~17.0.0", + "expo-constants": "~17.0.4", "invariant": "^2.2.4" }, "peerDependencies": { @@ -6068,12 +5978,12 @@ } }, "node_modules/expo-manifests": { - "version": "0.15.4", - "resolved": "https://registry.npmjs.org/expo-manifests/-/expo-manifests-0.15.4.tgz", - "integrity": "sha512-Ki6+twRbm+HTX3L8larhOdDbSYPG3ojGnZepR/+TGg3JF/5yyscosDVY6c6z8xEGjKIjs1F813yq9yAfiPh8/g==", + "version": "0.15.5", + "resolved": "https://registry.npmjs.org/expo-manifests/-/expo-manifests-0.15.5.tgz", + "integrity": "sha512-3X3eQomnTa4G0Y9GoJeyewHPTscuzWMrTB3x4CknqOyXpGOJjOuCKjhzvccHxXZAt0XswqBI94iTbqIofo9Uqw==", "license": "MIT", "dependencies": { - "@expo/config": "~10.0.4", + "@expo/config": "~10.0.8", "expo-json-utils": "~0.14.0" }, "peerDependencies": { @@ -6081,9 +5991,9 @@ } }, "node_modules/expo-modules-autolinking": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/expo-modules-autolinking/-/expo-modules-autolinking-2.0.4.tgz", - "integrity": "sha512-e0p+19NhmD50U7s7BV7kWIypWmTNC9n/VlJKlXS05hM/zX7pe6JKmXyb+BFnXJq3SLBalLCUY0tu2gEUF3XeVg==", + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/expo-modules-autolinking/-/expo-modules-autolinking-2.0.7.tgz", + "integrity": "sha512-rkGc6a/90AC3q8wSy4V+iIpq6Fd0KXmQICKrvfmSWwrMgJmLfwP4QTrvLYPYOOMjFwNJcTaohcH8vzW/wYKrMg==", "license": "MIT", "dependencies": { "@expo/spawn-async": "^1.7.2", @@ -6136,18 +6046,30 @@ } }, "node_modules/expo-modules-core": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/expo-modules-core/-/expo-modules-core-2.1.1.tgz", - "integrity": "sha512-yQzYCLR2mre4BNMXuqkeJ0oSNgmGEMI6BcmIzeNZbC2NFEjiaDpKvlV9bclYCtyVhUEVNbJcEPYMr6c1Y4eR4w==", + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/expo-modules-core/-/expo-modules-core-2.1.4.tgz", + "integrity": "sha512-gfsbTPSaocgcQQDy4Z4ztg1hcOofwODctAA+yoNcrUQr/hRaDc6ndIJQwGPjoGXnEbXVxFfzGGSAkNiqK1I7lQ==", "license": "MIT", "dependencies": { "invariant": "^2.2.4" } }, + "node_modules/expo-splash-screen": { + "version": "0.29.21", + "resolved": "https://registry.npmjs.org/expo-splash-screen/-/expo-splash-screen-0.29.21.tgz", + "integrity": "sha512-7uZ+qvIuNcvrvrLIklW+Wbt6llPuCj6LKYjrMu+GOX8s///laldS4TGiMAbqcE7fmfCzQ8ffgfY7xhxRourhcA==", + "license": "MIT", + "dependencies": { + "@expo/prebuild-config": "^8.0.25" + }, + "peerDependencies": { + "expo": "*" + } + }, "node_modules/expo-status-bar": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/expo-status-bar/-/expo-status-bar-2.0.0.tgz", - "integrity": "sha512-vxxdpvpNDMTEc5uTiIrbTvySKKUsOACmfl8OZuUdjNle05oGqwtq3v5YObwym/njSByjoyuZX8UpXBZnxvarwQ==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/expo-status-bar/-/expo-status-bar-2.0.1.tgz", + "integrity": "sha512-AkIPX7jWHRPp83UBZ1iXtVvyr0g+DgBVvIXTtlmPtmUsm8Vq9Bb5IGj86PW8osuFlgoTVAg7HI/+Ok7yEYwiRg==", "license": "MIT", "peerDependencies": { "react": "*", @@ -6155,12 +6077,12 @@ } }, "node_modules/expo-system-ui": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/expo-system-ui/-/expo-system-ui-4.0.6.tgz", - "integrity": "sha512-JWmw0aaNIB8YxA6bXgH6nClyledZaAG5VNzoRvmXT4+j3MY4waAHSSSdVV71bUgjchT/2KOAcibZ/EeosJONug==", + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/expo-system-ui/-/expo-system-ui-4.0.7.tgz", + "integrity": "sha512-x1VDoE7J8m4wxTgWyUBEYqsf1KabIg64dOLzYiZjg0cWOE6o6kX2Mg6n3abVWEEC01WhZBoo9+Urcce/6ZJ3tg==", "license": "MIT", "dependencies": { - "@react-native/normalize-colors": "0.76.5", + "@react-native/normalize-colors": "0.76.6", "debug": "^4.3.2" }, "peerDependencies": { @@ -6202,16 +6124,16 @@ "license": "MIT" }, "node_modules/fast-glob": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", - "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz", + "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==", "license": "MIT", "dependencies": { "@nodelib/fs.stat": "^2.0.2", "@nodelib/fs.walk": "^1.2.3", "glob-parent": "^5.1.2", "merge2": "^1.3.0", - "micromatch": "^4.0.4" + "micromatch": "^4.0.8" }, "engines": { "node": ">=8.6.0" @@ -6230,9 +6152,9 @@ "license": "BSD-3-Clause" }, "node_modules/fastq": { - "version": "1.17.1", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz", - "integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==", + "version": "1.18.0", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.18.0.tgz", + "integrity": "sha512-QKHXPW0hD8g4UET03SdOdunzSouc9N4AuHdsX8XNcTsuz+yYFILVNIX4l9yHABMhiEI9Db0JTTIpu0wB+Y1QQw==", "license": "ISC", "dependencies": { "reusify": "^1.0.4" @@ -6367,15 +6289,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/find-yarn-workspace-root": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/find-yarn-workspace-root/-/find-yarn-workspace-root-2.0.0.tgz", - "integrity": "sha512-1IMnbjt4KzsQfnhnzNd8wUEgXZ44IzZaZmnLYx7D5FZlaHt2gW20Cri8Q+E/t5tIj4+epTBub+2Zxu/vNILzqQ==", - "license": "Apache-2.0", - "dependencies": { - "micromatch": "^4.0.2" - } - }, "node_modules/flow-enums-runtime": { "version": "0.0.6", "resolved": "https://registry.npmjs.org/flow-enums-runtime/-/flow-enums-runtime-0.0.6.tgz", @@ -6524,30 +6437,6 @@ "node": "6.* || 8.* || >= 10.*" } }, - "node_modules/get-intrinsic": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.6.tgz", - "integrity": "sha512-qxsEs+9A+u85HhllWJJFicJfPDhRmjzoYdl64aMWW9yRIJmSyxdn8IEkuIM530/7T+lv0TIHd8L6Q/ra0tEoeA==", - "license": "MIT", - "dependencies": { - "call-bind-apply-helpers": "^1.0.1", - "dunder-proto": "^1.0.0", - "es-define-property": "^1.0.1", - "es-errors": "^1.3.0", - "es-object-atoms": "^1.0.0", - "function-bind": "^1.1.2", - "gopd": "^1.2.0", - "has-symbols": "^1.1.0", - "hasown": "^2.0.2", - "math-intrinsics": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/get-package-type": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz", @@ -6678,18 +6567,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/gopd": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", - "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/graceful-fs": { "version": "4.2.11", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", @@ -6705,30 +6582,6 @@ "node": ">=8" } }, - "node_modules/has-property-descriptors": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", - "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", - "license": "MIT", - "dependencies": { - "es-define-property": "^1.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-symbols": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", - "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/hasown": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", @@ -6847,9 +6700,9 @@ } }, "node_modules/image-size": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/image-size/-/image-size-1.1.1.tgz", - "integrity": "sha512-541xKlUw6jr/6gGuk92F+mYM5zaFAc5ahphvkqvNe2bQ6gVBkd6bfrmVJ2t4KDAfikAYZyIqTnktX3i6/aQDrQ==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/image-size/-/image-size-1.2.0.tgz", + "integrity": "sha512-4S8fwbO6w3GeCVN6OPtA9I5IGKkcDMPcKndtUlpJuCwu7JLjtj7JZpwqLuyY2nrmQT3AWsCJLSKPsc2mPBSl3w==", "license": "MIT", "dependencies": { "queue": "6.0.2" @@ -7105,12 +6958,6 @@ "node": ">=8" } }, - "node_modules/isarray": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", - "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", - "license": "MIT" - }, "node_modules/isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", @@ -7448,24 +7295,6 @@ "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", "license": "MIT" }, - "node_modules/json-stable-stringify": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.1.1.tgz", - "integrity": "sha512-SU/971Kt5qVQfJpyDveVhQ/vya+5hvrjClFOcr8c0Fq5aODJjMwutrOfCU+eCnVD5gpx1Q3fEqkyom77zH1iIg==", - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.5", - "isarray": "^2.0.5", - "jsonify": "^0.0.1", - "object-keys": "^1.1.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/json5": { "version": "2.2.3", "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", @@ -7487,15 +7316,6 @@ "graceful-fs": "^4.1.6" } }, - "node_modules/jsonify": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.1.tgz", - "integrity": "sha512-2/Ki0GcmuqSrgFyelQq9M05y7PS0mEwuIzrf3f1fPqkVDVRvZrPZtVSMHxdgo8Aq0sxAOb/cr2aqqA3LeWHVPg==", - "license": "Public Domain", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/kind-of": { "version": "6.0.3", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", @@ -7505,15 +7325,6 @@ "node": ">=0.10.0" } }, - "node_modules/klaw-sync": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/klaw-sync/-/klaw-sync-6.0.0.tgz", - "integrity": "sha512-nIeuVSzdCCs6TDPTqI8w1Yre34sSq7AkZ4B3sfOBbI2CgVSB4Du4aLQijFU2+lhAFCwt9+42Hel6lQNIv6AntQ==", - "license": "MIT", - "dependencies": { - "graceful-fs": "^4.1.11" - } - }, "node_modules/kleur": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", @@ -7982,15 +7793,6 @@ "integrity": "sha512-q9JtQJKjpsVxCRVgQ+WapguSbKC3SQ5HEzFGPAJMStgh3QjCawp00UKv3MTTAArTmGmmPUvllHZoNbZ3gs0I+Q==", "license": "Apache-2.0" }, - "node_modules/math-intrinsics": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.0.0.tgz", - "integrity": "sha512-4MqMiKP90ybymYvsut0CH2g4XWbfLtmlCkXmtmdcDCxNB+mQcu1w/1+L/VD7vi/PSv7X2JYV7SCcR+jiPXnQtA==", - "license": "MIT", - "engines": { - "node": ">= 0.4" - } - }, "node_modules/md5": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/md5/-/md5-2.3.0.tgz", @@ -8911,15 +8713,6 @@ "node": ">=0.10.0" } }, - "node_modules/object-keys": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", - "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", - "license": "MIT", - "engines": { - "node": ">= 0.4" - } - }, "node_modules/on-finished": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", @@ -9209,127 +9002,6 @@ "cross-spawn": "^7.0.3" } }, - "node_modules/patch-package": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/patch-package/-/patch-package-8.0.0.tgz", - "integrity": "sha512-da8BVIhzjtgScwDJ2TtKsfT5JFWz1hYoBl9rUQ1f38MC2HwnEIkK8VN3dKMKcP7P7bvvgzNDbfNHtx3MsQb5vA==", - "license": "MIT", - "dependencies": { - "@yarnpkg/lockfile": "^1.1.0", - "chalk": "^4.1.2", - "ci-info": "^3.7.0", - "cross-spawn": "^7.0.3", - "find-yarn-workspace-root": "^2.0.0", - "fs-extra": "^9.0.0", - "json-stable-stringify": "^1.0.2", - "klaw-sync": "^6.0.0", - "minimist": "^1.2.6", - "open": "^7.4.2", - "rimraf": "^2.6.3", - "semver": "^7.5.3", - "slash": "^2.0.0", - "tmp": "^0.0.33", - "yaml": "^2.2.2" - }, - "bin": { - "patch-package": "index.js" - }, - "engines": { - "node": ">=14", - "npm": ">5" - } - }, - "node_modules/patch-package/node_modules/fs-extra": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", - "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", - "license": "MIT", - "dependencies": { - "at-least-node": "^1.0.0", - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/patch-package/node_modules/glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "deprecated": "Glob versions prior to v9 are no longer supported", - "license": "ISC", - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/patch-package/node_modules/jsonfile": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", - "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", - "license": "MIT", - "dependencies": { - "universalify": "^2.0.0" - }, - "optionalDependencies": { - "graceful-fs": "^4.1.6" - } - }, - "node_modules/patch-package/node_modules/rimraf": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", - "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", - "deprecated": "Rimraf versions prior to v4 are no longer supported", - "license": "ISC", - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - } - }, - "node_modules/patch-package/node_modules/semver": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/patch-package/node_modules/slash": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz", - "integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==", - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/patch-package/node_modules/universalify": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", - "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", - "license": "MIT", - "engines": { - "node": ">= 10.0.0" - } - }, "node_modules/path-browserify": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-1.0.1.tgz", @@ -9733,6 +9405,15 @@ "node": ">=6" } }, + "node_modules/pusher-js": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/pusher-js/-/pusher-js-8.3.0.tgz", + "integrity": "sha512-6GohP06WlVeomAQQe9qWh1IDzd3+InluWt+ZUOcecVK1SEQkg6a8uYVsvxSJm7cbccfmHhE0jDkmhKIhue8vmA==", + "license": "MIT", + "dependencies": { + "tweetnacl": "^1.0.3" + } + }, "node_modules/qrcode-terminal": { "version": "0.11.0", "resolved": "https://registry.npmjs.org/qrcode-terminal/-/qrcode-terminal-0.11.0.tgz", @@ -9874,19 +9555,19 @@ "license": "MIT" }, "node_modules/react-native": { - "version": "0.76.5", - "resolved": "https://registry.npmjs.org/react-native/-/react-native-0.76.5.tgz", - "integrity": "sha512-op2p2kB+lqMF1D7AdX4+wvaR0OPFbvWYs+VBE7bwsb99Cn9xISrLRLAgFflZedQsa5HvnOGrULhtnmItbIKVVw==", + "version": "0.76.6", + "resolved": "https://registry.npmjs.org/react-native/-/react-native-0.76.6.tgz", + "integrity": "sha512-AsRi+ud6v6ADH7ZtSOY42kRB4nbM0KtSu450pGO4pDudl4AEK/AF96ai88snb2/VJJSGGa/49QyJVFXxz/qoFg==", "license": "MIT", "dependencies": { "@jest/create-cache-key-function": "^29.6.3", - "@react-native/assets-registry": "0.76.5", - "@react-native/codegen": "0.76.5", - "@react-native/community-cli-plugin": "0.76.5", - "@react-native/gradle-plugin": "0.76.5", - "@react-native/js-polyfills": "0.76.5", - "@react-native/normalize-colors": "0.76.5", - "@react-native/virtualized-lists": "0.76.5", + "@react-native/assets-registry": "0.76.6", + "@react-native/codegen": "0.76.6", + "@react-native/community-cli-plugin": "0.76.6", + "@react-native/gradle-plugin": "0.76.6", + "@react-native/js-polyfills": "0.76.6", + "@react-native/normalize-colors": "0.76.6", + "@react-native/virtualized-lists": "0.76.6", "abort-controller": "^3.0.0", "anser": "^1.4.9", "ansi-regex": "^5.0.0", @@ -9972,6 +9653,20 @@ "react-native": ">=0.56" } }, + "node_modules/react-native-nfc-manager": { + "version": "3.16.1", + "resolved": "https://registry.npmjs.org/react-native-nfc-manager/-/react-native-nfc-manager-3.16.1.tgz", + "integrity": "sha512-rYhJSThAxAT4AVpZzZJc3X1jiTnZQlmrzk9DeeWLstUTXCoECt/75brLgn+EiXK+AfONnMnFdsSzIyruVWyIdw==", + "license": "MIT", + "peerDependencies": { + "@expo/config-plugins": "8 || 9" + }, + "peerDependenciesMeta": { + "@expo/config-plugins": { + "optional": true + } + } + }, "node_modules/react-native-paper": { "version": "5.12.5", "resolved": "https://registry.npmjs.org/react-native-paper/-/react-native-paper-5.12.5.tgz", @@ -10058,9 +9753,9 @@ } }, "node_modules/react-native-screens": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/react-native-screens/-/react-native-screens-4.1.0.tgz", - "integrity": "sha512-tCBwe7fRMpoi/nIgZxE86N8b2SH8d5PlfGaQO8lgqlXqIyvwqm3u1HJCaA0tsacPyzhW7vVtRfQyq9e1j0S2gA==", + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/react-native-screens/-/react-native-screens-4.4.0.tgz", + "integrity": "sha512-c7zc7Zwjty6/pGyuuvh9gK3YBYqHPOxrhXfG1lF4gHlojQSmIx2piNbNaV+Uykj+RDTmFXK0e/hA+fucw/Qozg==", "license": "MIT", "dependencies": { "react-freeze": "^1.0.0", @@ -10830,23 +10525,6 @@ "node": ">= 0.8" } }, - "node_modules/set-function-length": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", - "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", - "license": "MIT", - "dependencies": { - "define-data-property": "^1.1.4", - "es-errors": "^1.3.0", - "function-bind": "^1.1.2", - "get-intrinsic": "^1.2.4", - "gopd": "^1.0.1", - "has-property-descriptors": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - } - }, "node_modules/setimmediate": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", @@ -11350,6 +11028,7 @@ "version": "8.2.5", "resolved": "https://registry.npmjs.org/sudo-prompt/-/sudo-prompt-8.2.5.tgz", "integrity": "sha512-rlBo3HU/1zAJUrkY6jNxDOC9eVYliG6nS4JA8u8KAshITd07tafMc/Br7xQwCSseXwJ2iCcHCE8SNWX3q8Z+kw==", + "deprecated": "Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.", "license": "MIT" }, "node_modules/supports-color": { @@ -11812,6 +11491,12 @@ "node": "*" } }, + "node_modules/tweetnacl": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-1.0.3.tgz", + "integrity": "sha512-6rt+RN7aOi1nGMyC4Xa5DdYiukl2UWCbcJft7YhxReBGQD7OAM8Pbxw6YMo4r2diNEA8FEmu32YOn9rhaiE5yw==", + "license": "Unlicense" + }, "node_modules/type-detect": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", @@ -11873,9 +11558,9 @@ } }, "node_modules/undici": { - "version": "6.21.0", - "resolved": "https://registry.npmjs.org/undici/-/undici-6.21.0.tgz", - "integrity": "sha512-BUgJXc752Kou3oOIuU1i+yZZypyZRqNPW0vqoMPl8VaoalSfeR0D8/t4iAS3yirs79SSMTxTag+ZC86uswv+Cw==", + "version": "6.21.1", + "resolved": "https://registry.npmjs.org/undici/-/undici-6.21.1.tgz", + "integrity": "sha512-q/1rj5D0/zayJB2FraXdaWxbhWiNKDvu8naDT2dl1yTlvJp4BLtOcp2a5BvgGNQpYYJzau7tf1WgKv3b+7mqpQ==", "license": "MIT", "engines": { "node": ">=18.17" @@ -12396,18 +12081,6 @@ "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", "license": "ISC" }, - "node_modules/yaml": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.6.1.tgz", - "integrity": "sha512-7r0XPzioN/Q9kXBro/XPnA6kznR73DHq+GXh5ON7ZozRO6aMjbmiBuKste2wslTFkC5d1dw0GooOCepZXJ2SAg==", - "license": "ISC", - "bin": { - "yaml": "bin.mjs" - }, - "engines": { - "node": ">= 14" - } - }, "node_modules/yargs": { "version": "17.7.2", "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", diff --git a/amnet-native/package.json b/amnet-native/package.json index a7f3e7b..b2ed706 100644 --- a/amnet-native/package.json +++ b/amnet-native/package.json @@ -6,9 +6,10 @@ "android": "expo run:android", "ios": "expo run:ios", "ios-prebuild": "expo prebuild --platform ios", - "postinstall": "patch-package" + "android-prebuild": "expo prebuild --platform android" }, "dependencies": { + "@babel/runtime": "^7.26.0", "@expo-google-fonts/jetbrains-mono": "^0.2.3", "@react-navigation/bottom-tabs": "^6.6.1", "@react-navigation/native": "^6.1.18", @@ -17,29 +18,31 @@ "@types/react": "~18.3.12", "amnet-shared": "file:../amnet-shared", "date-fns": "^3.6.0", - "expo": "^52.0.0", - "expo-blur": "~14.0.1", - "expo-build-properties": "^0.13.1", - "expo-clipboard": "~7.0.0", + "expo": "^52.0.27", + "expo-blur": "~14.0.3", + "expo-build-properties": "~0.13.2", + "expo-clipboard": "~7.0.1", "expo-constants": "~17.0.3", - "expo-dev-client": "~5.0.4", - "expo-linking": "~7.0.3", - "expo-status-bar": "~2.0.0", - "expo-system-ui": "~4.0.4", + "expo-dev-client": "~5.0.10", + "expo-linking": "~7.0.4", + "expo-status-bar": "~2.0.1", + "expo-system-ui": "~4.0.7", "lucide-react-native": "^0.427.0", - "patch-package": "^8.0.0", + "pusher-js": "^8.2.0", "react": "18.3.1", - "react-native": "0.76.5", + "react-native": "0.76.6", "react-native-context-menu-view": "^1.16.0", "react-native-gesture-handler": "~2.20.2", "react-native-get-random-values": "^1.11.0", + "react-native-nfc-manager": "^3.16.1", "react-native-paper": "^5.12.5", "react-native-reanimated": "~3.16.1", "react-native-safe-area-context": "4.12.0", - "react-native-screens": "~4.1.0", + "react-native-screens": "~4.4.0", "react-native-svg": "15.8.0", "react-native-url-polyfill": "^2.0.0", "realm": "^12.14.0", - "typescript": "~5.3.3" + "typescript": "~5.3.3", + "expo-splash-screen": "~0.29.21" } } diff --git a/amnet-native/patches/expo-modules-core+1.12.20.patch b/amnet-native/patches/expo-modules-core+1.12.20.patch deleted file mode 100644 index 1400102..0000000 --- a/amnet-native/patches/expo-modules-core+1.12.20.patch +++ /dev/null @@ -1,64 +0,0 @@ -diff --git a/node_modules/expo-modules-core/ios/AppDelegates/ExpoAppDelegate.swift b/node_modules/expo-modules-core/ios/AppDelegates/ExpoAppDelegate.swift -index 8ba09a7..8d7d2b0 100644 ---- a/node_modules/expo-modules-core/ios/AppDelegates/ExpoAppDelegate.swift -+++ b/node_modules/expo-modules-core/ios/AppDelegates/ExpoAppDelegate.swift -@@ -101,59 +101,6 @@ open class ExpoAppDelegate: UIResponder, UIApplicationDelegate { - } - } - -- // MARK: - Handling Remote Notification Registration -- -- open func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) { -- subscribers.forEach { $0.application?(application, didRegisterForRemoteNotificationsWithDeviceToken: deviceToken) } -- } -- -- open func application(_ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: Error) { -- subscribers.forEach { $0.application?(application, didFailToRegisterForRemoteNotificationsWithError: error) } -- } -- -- open func application( -- _ application: UIApplication, -- didReceiveRemoteNotification userInfo: [AnyHashable: Any], -- fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void -- ) { -- let selector = #selector(application(_:didReceiveRemoteNotification:fetchCompletionHandler:)) -- let subs = subscribers.filter { $0.responds(to: selector) } -- var subscribersLeft = subs.count -- let dispatchQueue = DispatchQueue(label: "expo.application.remoteNotification", qos: .userInteractive) -- var failedCount = 0 -- var newDataCount = 0 -- -- let handler = { (result: UIBackgroundFetchResult) in -- dispatchQueue.sync { -- if result == .failed { -- failedCount += 1 -- } else if result == .newData { -- newDataCount += 1 -- } -- -- subscribersLeft -= 1 -- -- if subscribersLeft == 0 { -- if newDataCount > 0 { -- completionHandler(.newData) -- } else if failedCount > 0 { -- completionHandler(.failed) -- } else { -- completionHandler(.noData) -- } -- } -- } -- } -- -- if subs.isEmpty { -- completionHandler(.noData) -- } else { -- subs.forEach { subscriber in -- subscriber.application?(application, didReceiveRemoteNotification: userInfo, fetchCompletionHandler: handler) -- } -- } -- } -- - // MARK: - Continuing User Activity and Handling Quick Actions - - open func application(_ application: UIApplication, willContinueUserActivityWithType userActivityType: String) -> Bool { diff --git a/amnet-native/utils/ModalStyles.ts b/amnet-native/utils/ModalStyles.ts index 8b6ba2c..b3a0ac6 100644 --- a/amnet-native/utils/ModalStyles.ts +++ b/amnet-native/utils/ModalStyles.ts @@ -13,7 +13,14 @@ const modalStyles = StyleSheet.create({ }, formItemDivider: { marginVertical: 15 - } + }, + rootLayout: { + display: "flex", + gap: 10, + justifyContent: "center", + paddingHorizontal: 15, + paddingTop: 25 + }, }); export function useModalStyles() { diff --git a/amnet-shared/dist/index.d.mts b/amnet-shared/dist/index.d.mts index ad11302..ab3c7f9 100644 --- a/amnet-shared/dist/index.d.mts +++ b/amnet-shared/dist/index.d.mts @@ -8,6 +8,7 @@ declare const AMNET_API_VERSION = 1; declare const MIN_AMNET_API_VERSION = 1; interface AMCardInRequest { cardId: string; + physicalCardIDm?: string; } /** * Server connection info (api version, address, etc.) @@ -49,6 +50,7 @@ declare function performCardIn(server: AMServerConnectionInfo, request: AMCardIn declare function fetchServerInfo(serverAddress: string, abort: AbortSignal): Promise; declare const CARD_ID_REGEX: RegExp; +declare const AMNET_COMPANY_ID = 597; declare function generateCardNumber(): string; /** * Validates the provided card id by known parameters @@ -62,4 +64,11 @@ declare function validateCardId(id: string): boolean; */ declare function getGameName(id: string): string | null; -export { type AMCardInRequest, AMNET_API_VERSION, type AMServerConnectionInfo, type AMServerInfo, type AMServerInstanceMetrics, type AMServerMetadata, CARD_ID_REGEX, MIN_AMNET_API_VERSION, fetchServerInfo, generateCardNumber, getGameName, performCardIn, validateCardId }; +type DecodedAccessCode = { + revision: number; + serial: number; +}; +declare function decodeAccessCode(code: string): DecodedAccessCode | null; +declare function encodeAccessCode(company: number, serial: number, rev?: number): string; + +export { type AMCardInRequest, AMNET_API_VERSION, AMNET_COMPANY_ID, type AMServerConnectionInfo, type AMServerInfo, type AMServerInstanceMetrics, type AMServerMetadata, CARD_ID_REGEX, decodeAccessCode as DecodeAMAccessCode, encodeAccessCode as EncodeAMAccessCode, MIN_AMNET_API_VERSION, fetchServerInfo, generateCardNumber, getGameName, performCardIn, validateCardId }; diff --git a/amnet-shared/dist/index.d.ts b/amnet-shared/dist/index.d.ts index ad11302..ab3c7f9 100644 --- a/amnet-shared/dist/index.d.ts +++ b/amnet-shared/dist/index.d.ts @@ -8,6 +8,7 @@ declare const AMNET_API_VERSION = 1; declare const MIN_AMNET_API_VERSION = 1; interface AMCardInRequest { cardId: string; + physicalCardIDm?: string; } /** * Server connection info (api version, address, etc.) @@ -49,6 +50,7 @@ declare function performCardIn(server: AMServerConnectionInfo, request: AMCardIn declare function fetchServerInfo(serverAddress: string, abort: AbortSignal): Promise; declare const CARD_ID_REGEX: RegExp; +declare const AMNET_COMPANY_ID = 597; declare function generateCardNumber(): string; /** * Validates the provided card id by known parameters @@ -62,4 +64,11 @@ declare function validateCardId(id: string): boolean; */ declare function getGameName(id: string): string | null; -export { type AMCardInRequest, AMNET_API_VERSION, type AMServerConnectionInfo, type AMServerInfo, type AMServerInstanceMetrics, type AMServerMetadata, CARD_ID_REGEX, MIN_AMNET_API_VERSION, fetchServerInfo, generateCardNumber, getGameName, performCardIn, validateCardId }; +type DecodedAccessCode = { + revision: number; + serial: number; +}; +declare function decodeAccessCode(code: string): DecodedAccessCode | null; +declare function encodeAccessCode(company: number, serial: number, rev?: number): string; + +export { type AMCardInRequest, AMNET_API_VERSION, AMNET_COMPANY_ID, type AMServerConnectionInfo, type AMServerInfo, type AMServerInstanceMetrics, type AMServerMetadata, CARD_ID_REGEX, decodeAccessCode as DecodeAMAccessCode, encodeAccessCode as EncodeAMAccessCode, MIN_AMNET_API_VERSION, fetchServerInfo, generateCardNumber, getGameName, performCardIn, validateCardId }; diff --git a/amnet-shared/dist/index.js b/amnet-shared/dist/index.js index fb2c6ec..99261a3 100644 --- a/amnet-shared/dist/index.js +++ b/amnet-shared/dist/index.js @@ -1,10 +1,12 @@ "use strict"; +var __create = Object.create; var __defProp = Object.defineProperty; var __defProps = Object.defineProperties; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropDescs = Object.getOwnPropertyDescriptors; var __getOwnPropNames = Object.getOwnPropertyNames; var __getOwnPropSymbols = Object.getOwnPropertySymbols; +var __getProtoOf = Object.getPrototypeOf; var __hasOwnProp = Object.prototype.hasOwnProperty; var __propIsEnum = Object.prototype.propertyIsEnumerable; var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value; @@ -32,33 +34,24 @@ var __copyProps = (to, from, except, desc) => { } return to; }; +var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps( + // If the importer is in node compatibility mode or this is not an ESM + // file that has been converted to a CommonJS file using a Babel- + // compatible transform (i.e. "__esModule" has not been set), then set + // "default" to the CommonJS "module.exports" for node compatibility. + isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, + mod +)); var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); -var __async = (__this, __arguments, generator) => { - return new Promise((resolve, reject) => { - var fulfilled = (value) => { - try { - step(generator.next(value)); - } catch (e) { - reject(e); - } - }; - var rejected = (value) => { - try { - step(generator.throw(value)); - } catch (e) { - reject(e); - } - }; - var step = (x) => x.done ? resolve(x.value) : Promise.resolve(x.value).then(fulfilled, rejected); - step((generator = generator.apply(__this, __arguments)).next()); - }); -}; // src/index.ts var src_exports = {}; __export(src_exports, { AMNET_API_VERSION: () => AMNET_API_VERSION, + AMNET_COMPANY_ID: () => AMNET_COMPANY_ID, CARD_ID_REGEX: () => CARD_ID_REGEX, + DecodeAMAccessCode: () => decodeAccessCode, + EncodeAMAccessCode: () => encodeAccessCode, MIN_AMNET_API_VERSION: () => MIN_AMNET_API_VERSION, fetchServerInfo: () => fetchServerInfo, generateCardNumber: () => generateCardNumber, @@ -71,59 +64,117 @@ module.exports = __toCommonJS(src_exports); // src/api.ts var AMNET_API_VERSION = 1; var MIN_AMNET_API_VERSION = 1; -function performCardIn(server, request, signal) { - return __async(this, null, function* () { - if (server.apiVersion < MIN_AMNET_API_VERSION || server.apiVersion > AMNET_API_VERSION) { - throw new Error("Unsupported server API version"); - } - try { - const response = yield fetch(`${new URL(server.serverAddress).origin}/amnet/signin`, { - method: "POST", - headers: { - "Content-Type": "application/json" - }, - body: JSON.stringify(request), - signal - }); - return response.ok; - } catch (e) { - return false; - } - }); +async function performCardIn(server, request, signal) { + if (server.apiVersion < MIN_AMNET_API_VERSION || server.apiVersion > AMNET_API_VERSION) { + throw new Error("Unsupported server API version"); + } + try { + const response = await fetch(`${new URL(server.serverAddress).origin}/amnet/signin`, { + method: "POST", + headers: { + "Content-Type": "application/json" + }, + body: JSON.stringify(request), + signal + }); + return response.ok; + } catch (e) { + return false; + } } -function fetchServerInfo(serverAddress, abort) { - return __async(this, null, function* () { - try { - const response = yield fetch(`${new URL(serverAddress).origin}/amnet/info`, { - signal: abort - }); - if (!response.ok) { - return null; - } - return __spreadProps(__spreadValues({}, yield response.json()), { - serverAddress - }); - } catch (e) { +async function fetchServerInfo(serverAddress, abort) { + try { + const response = await fetch(`${new URL(serverAddress).origin}/amnet/info`, { + signal: abort + }); + if (!response.ok) { return null; } - }); + return __spreadProps(__spreadValues({}, await response.json()), { + serverAddress + }); + } catch (e) { + return null; + } +} + +// src/card-encoding.ts +var import_lodash = __toESM(require("lodash")); +var import_big_integer = __toESM(require("big-integer")); +var sbtable = [[[45, 50, 94, 2, 66, 55, 56, 49, 99, 36, 60, 0, 73, 30, 39, 37, 80, 74, 85, 7, 12, 33, 93, 83, 95, 91, 98, 92, 23, 24, 79, 21, 31, 35, 71, 70, 4, 43, 1, 5, 88, 90, 69, 58, 76, 20, 84, 62, 77, 44, 61, 11, 16, 53, 82, 34, 13, 47, 48, 87, 89, 15, 64, 3, 54, 28, 57, 67, 9, 75, 32, 65, 96, 17, 18, 29, 10, 14, 42, 6, 46, 26, 40, 59, 63, 78, 68, 8, 86, 51, 25, 72, 38, 97, 19, 81, 27, 41, 52, 22], [26, 32, 34, 79, 42, 45, 4, 75, 22, 73, 64, 98, 49, 19, 5, 24, 6, 55, 63, 25, 40, 77, 54, 12, 9, 44, 83, 71, 0, 90, 97, 96, 81, 80, 3, 31, 56, 92, 17, 86, 72, 28, 36, 78, 62, 30, 7, 46, 87, 20, 82, 50, 35, 61, 41, 94, 68, 11, 1, 10, 74, 67, 85, 43, 57, 15, 95, 84, 65, 53, 69, 52, 76, 88, 2, 14, 37, 58, 93, 16, 59, 51, 18, 99, 39, 47, 89, 8, 13, 91, 38, 33, 70, 48, 23, 29, 27, 66, 60, 21], [28, 53, 30, 85, 0, 95, 70, 47, 40, 51, 94, 68, 99, 15, 5, 57, 1, 16, 80, 93, 91, 52, 2, 32, 48, 77, 41, 75, 22, 39, 50, 81, 79, 73, 97, 76, 60, 4, 59, 25, 78, 38, 46, 58, 90, 84, 56, 6, 83, 62, 42, 10, 64, 31, 36, 61, 65, 63, 18, 8, 9, 96, 55, 26, 89, 67, 3, 98, 35, 21, 13, 12, 88, 71, 37, 29, 87, 49, 24, 86, 92, 20, 44, 74, 69, 17, 82, 54, 27, 7, 23, 66, 11, 19, 34, 45, 14, 72, 43, 33], [32, 44, 86, 79, 38, 61, 25, 8, 5, 85, 78, 48, 33, 87, 84, 35, 64, 41, 60, 21, 96, 75, 6, 69, 39, 94, 3, 92, 37, 77, 15, 13, 29, 59, 76, 91, 65, 56, 73, 83, 27, 62, 89, 50, 18, 98, 81, 17, 71, 28, 82, 11, 30, 43, 34, 20, 70, 22, 46, 63, 52, 68, 90, 53, 36, 10, 74, 58, 40, 88, 9, 2, 42, 26, 24, 4, 95, 57, 31, 66, 0, 14, 49, 16, 99, 19, 51, 23, 47, 12, 93, 1, 7, 80, 45, 97, 55, 67, 72, 54], [58, 35, 42, 38, 63, 36, 68, 30, 81, 4, 87, 80, 32, 69, 37, 67, 1, 86, 61, 94, 27, 11, 84, 26, 59, 73, 53, 66, 72, 71, 39, 33, 99, 8, 43, 88, 17, 22, 89, 5, 46, 93, 98, 48, 55, 83, 34, 3, 0, 16, 12, 20, 78, 9, 2, 76, 54, 51, 25, 24, 62, 57, 92, 10, 50, 28, 79, 23, 52, 95, 44, 60, 74, 90, 19, 77, 21, 31, 96, 49, 64, 6, 29, 85, 18, 13, 82, 47, 56, 45, 15, 7, 97, 75, 40, 41, 65, 14, 70, 91], [81, 82, 66, 72, 83, 4, 20, 94, 53, 48, 77, 41, 67, 64, 9, 24, 36, 55, 14, 1, 78, 84, 49, 0, 44, 58, 70, 25, 28, 73, 8, 68, 88, 54, 86, 87, 23, 52, 27, 5, 97, 37, 62, 50, 3, 89, 92, 47, 30, 10, 29, 80, 22, 26, 11, 13, 69, 60, 38, 90, 85, 57, 12, 75, 46, 39, 74, 33, 42, 93, 98, 91, 59, 99, 18, 6, 17, 16, 32, 40, 63, 7, 76, 15, 43, 71, 51, 35, 2, 65, 34, 96, 19, 56, 79, 21, 95, 45, 61, 31], [25, 88, 7, 57, 98, 63, 86, 13, 69, 84, 56, 20, 68, 90, 35, 6, 43, 93, 95, 3, 75, 4, 9, 28, 31, 66, 21, 44, 30, 76, 11, 22, 49, 2, 77, 40, 85, 19, 82, 16, 97, 92, 39, 96, 18, 32, 42, 94, 70, 71, 54, 79, 67, 78, 37, 12, 99, 53, 61, 41, 87, 17, 1, 14, 52, 10, 47, 58, 27, 46, 36, 55, 26, 15, 33, 50, 72, 51, 89, 23, 74, 59, 64, 8, 83, 65, 80, 29, 38, 0, 60, 24, 45, 81, 48, 91, 73, 5, 34, 62], [73, 85, 37, 11, 80, 46, 16, 47, 88, 65, 94, 64, 12, 38, 98, 70, 95, 48, 92, 18, 56, 75, 58, 7, 81, 15, 74, 13, 5, 44, 27, 32, 76, 90, 33, 55, 26, 96, 77, 24, 0, 89, 8, 4, 28, 39, 71, 3, 10, 41, 91, 53, 31, 68, 36, 17, 69, 60, 34, 54, 93, 82, 21, 51, 87, 59, 61, 6, 1, 23, 30, 66, 43, 25, 35, 42, 49, 78, 62, 14, 19, 20, 29, 22, 52, 83, 63, 45, 2, 99, 50, 79, 72, 40, 84, 97, 86, 57, 67, 9], [48, 94, 17, 55, 59, 24, 72, 75, 38, 85, 34, 98, 95, 36, 49, 63, 57, 54, 29, 6, 52, 47, 73, 1, 82, 9, 66, 83, 31, 61, 78, 60, 97, 14, 87, 15, 90, 70, 53, 10, 27, 8, 3, 64, 51, 50, 68, 26, 22, 19, 42, 96, 67, 7, 25, 39, 92, 30, 58, 93, 21, 74, 41, 18, 65, 44, 88, 32, 71, 69, 12, 77, 13, 11, 99, 79, 37, 89, 81, 35, 86, 56, 45, 76, 46, 80, 62, 43, 16, 84, 40, 5, 33, 91, 4, 20, 0, 23, 28, 2], [61, 45, 79, 13, 59, 52, 6, 77, 3, 31, 70, 80, 26, 33, 36, 4, 27, 32, 24, 74, 29, 94, 16, 12, 76, 7, 88, 57, 78, 42, 97, 96, 43, 83, 92, 21, 51, 47, 49, 58, 90, 41, 93, 98, 35, 63, 86, 37, 5, 30, 28, 72, 25, 22, 60, 19, 39, 34, 68, 50, 8, 64, 46, 99, 84, 87, 69, 56, 53, 55, 44, 54, 89, 65, 85, 0, 71, 15, 17, 66, 81, 82, 91, 95, 62, 48, 38, 75, 40, 14, 9, 10, 73, 67, 18, 11, 23, 2, 20, 1]], [[95, 90, 61, 38, 18, 7, 83, 39, 79, 14, 48, 21, 81, 44, 78, 50, 56, 91, 12, 86, 99, 98, 43, 63, 73, 87, 42, 72, 15, 68, 97, 23, 88, 69, 2, 51, 19, 58, 59, 22, 20, 29, 82, 11, 75, 70, 9, 71, 27, 30, 47, 89, 92, 60, 46, 76, 93, 54, 1, 96, 94, 57, 40, 62, 41, 3, 28, 64, 37, 74, 67, 16, 65, 53, 5, 36, 24, 45, 32, 33, 10, 85, 26, 4, 84, 77, 35, 13, 6, 8, 17, 80, 25, 55, 52, 66, 49, 34, 0, 31], [18, 14, 70, 43, 74, 45, 94, 36, 40, 6, 31, 46, 15, 47, 13, 19, 72, 61, 99, 21, 17, 92, 88, 78, 73, 90, 0, 96, 20, 28, 25, 51, 50, 77, 29, 16, 54, 12, 58, 38, 71, 23, 42, 83, 65, 60, 10, 33, 22, 76, 95, 32, 57, 5, 59, 67, 68, 3, 91, 85, 26, 62, 41, 1, 53, 82, 34, 24, 87, 27, 89, 75, 56, 30, 81, 7, 8, 4, 64, 66, 9, 63, 35, 52, 80, 93, 69, 84, 55, 86, 48, 98, 79, 97, 49, 44, 39, 11, 37, 2], [76, 16, 73, 29, 34, 14, 36, 90, 58, 70, 46, 2, 91, 59, 63, 32, 84, 40, 78, 38, 19, 37, 0, 31, 8, 44, 94, 39, 10, 66, 42, 1, 21, 88, 82, 97, 33, 4, 99, 74, 89, 62, 25, 87, 77, 43, 50, 95, 64, 23, 47, 93, 65, 27, 12, 71, 9, 72, 60, 18, 7, 22, 79, 24, 96, 45, 49, 98, 57, 11, 5, 86, 3, 80, 26, 51, 17, 85, 54, 67, 48, 35, 53, 41, 28, 13, 20, 92, 83, 69, 6, 68, 75, 52, 61, 30, 81, 56, 15, 55], [0, 62, 25, 61, 56, 87, 54, 27, 75, 49, 18, 69, 17, 71, 40, 6, 90, 80, 23, 26, 68, 24, 10, 21, 47, 88, 36, 55, 15, 22, 48, 12, 83, 99, 46, 67, 59, 29, 58, 73, 78, 97, 19, 33, 51, 98, 65, 91, 16, 4, 63, 41, 3, 70, 30, 8, 89, 34, 72, 60, 9, 95, 50, 2, 66, 53, 44, 85, 28, 5, 92, 43, 64, 96, 74, 77, 45, 52, 14, 42, 1, 32, 20, 76, 86, 82, 94, 7, 39, 13, 31, 11, 84, 93, 35, 37, 38, 57, 79, 81], [78, 8, 59, 25, 69, 15, 63, 3, 57, 5, 50, 96, 41, 66, 80, 81, 7, 45, 60, 74, 79, 32, 27, 58, 56, 82, 11, 47, 17, 85, 53, 40, 95, 84, 76, 92, 18, 71, 64, 51, 67, 91, 22, 34, 65, 31, 73, 93, 68, 75, 77, 37, 43, 12, 20, 99, 2, 1, 19, 35, 44, 55, 90, 9, 0, 6, 33, 89, 24, 14, 97, 10, 48, 61, 23, 54, 98, 86, 88, 94, 46, 70, 28, 36, 16, 30, 4, 39, 26, 38, 87, 52, 83, 49, 62, 42, 72, 29, 13, 21], [20, 88, 35, 5, 85, 98, 11, 78, 62, 83, 79, 80, 40, 14, 91, 8, 7, 69, 71, 61, 49, 38, 64, 82, 0, 47, 84, 95, 2, 50, 77, 41, 97, 36, 33, 81, 46, 21, 73, 48, 31, 92, 54, 89, 87, 60, 90, 10, 76, 45, 99, 52, 3, 44, 39, 43, 18, 16, 63, 12, 28, 70, 86, 6, 4, 24, 59, 30, 96, 65, 22, 56, 74, 23, 32, 75, 53, 93, 15, 67, 66, 17, 29, 25, 42, 37, 57, 9, 72, 68, 26, 34, 27, 51, 19, 58, 55, 94, 13, 1], [72, 53, 79, 61, 30, 33, 25, 75, 8, 55, 14, 6, 22, 93, 18, 77, 4, 74, 44, 36, 82, 94, 2, 5, 62, 54, 28, 3, 63, 97, 65, 7, 84, 73, 39, 92, 67, 91, 24, 45, 15, 81, 19, 78, 80, 64, 34, 43, 32, 87, 52, 95, 89, 37, 10, 23, 20, 68, 42, 47, 59, 58, 49, 71, 40, 85, 13, 31, 12, 57, 96, 90, 56, 41, 48, 9, 99, 35, 98, 26, 1, 46, 11, 69, 27, 83, 60, 50, 21, 70, 0, 88, 29, 86, 76, 16, 66, 38, 51, 17], [3, 68, 86, 94, 81, 90, 85, 32, 65, 52, 50, 42, 80, 78, 26, 93, 57, 58, 69, 82, 92, 27, 11, 67, 95, 41, 21, 88, 35, 17, 19, 15, 22, 62, 40, 76, 63, 59, 37, 55, 75, 9, 24, 89, 56, 53, 23, 60, 25, 6, 1, 71, 16, 7, 10, 44, 8, 12, 87, 64, 54, 72, 20, 33, 70, 79, 14, 97, 4, 99, 45, 39, 2, 77, 98, 74, 49, 30, 13, 61, 66, 73, 47, 43, 96, 83, 18, 91, 28, 48, 38, 34, 31, 36, 29, 0, 84, 46, 5, 51], [71, 84, 25, 70, 77, 56, 61, 47, 72, 27, 54, 89, 9, 46, 95, 59, 42, 98, 63, 69, 48, 16, 97, 14, 66, 83, 87, 68, 17, 2, 15, 79, 31, 1, 57, 12, 33, 36, 0, 40, 21, 50, 76, 41, 10, 13, 44, 5, 53, 4, 38, 35, 55, 96, 81, 91, 90, 64, 34, 51, 6, 28, 32, 39, 75, 18, 93, 24, 78, 7, 52, 43, 49, 37, 74, 8, 58, 65, 92, 67, 85, 20, 94, 88, 80, 86, 19, 60, 3, 11, 30, 45, 29, 22, 26, 73, 99, 23, 62, 82], [67, 91, 46, 33, 76, 3, 96, 23, 9, 68, 49, 63, 1, 92, 58, 62, 69, 77, 70, 75, 71, 94, 51, 55, 50, 52, 0, 88, 18, 16, 73, 6, 12, 87, 93, 79, 84, 57, 48, 41, 20, 47, 15, 42, 54, 81, 7, 30, 34, 56, 29, 8, 98, 5, 45, 64, 83, 74, 22, 82, 80, 95, 2, 72, 44, 31, 86, 78, 13, 10, 28, 89, 60, 35, 61, 19, 14, 85, 4, 43, 11, 40, 26, 99, 39, 32, 90, 17, 24, 37, 36, 21, 25, 53, 97, 59, 27, 38, 65, 66]], [[40, 77, 66, 65, 97, 96, 58, 64, 69, 30, 0, 3, 17, 33, 51, 23, 59, 10, 7, 20, 29, 49, 71, 13, 46, 4, 79, 92, 47, 18, 72, 57, 73, 80, 56, 28, 78, 67, 9, 87, 43, 31, 22, 62, 75, 99, 19, 63, 35, 93, 12, 98, 25, 26, 37, 89, 86, 15, 55, 50, 91, 38, 42, 81, 2, 94, 70, 68, 45, 88, 76, 74, 11, 24, 41, 60, 85, 21, 44, 32, 82, 61, 52, 83, 53, 36, 48, 1, 95, 27, 14, 84, 54, 6, 39, 34, 90, 5, 16, 8], [44, 69, 53, 28, 18, 11, 23, 65, 96, 25, 93, 42, 72, 58, 95, 56, 32, 21, 78, 77, 51, 34, 47, 7, 66, 13, 88, 67, 92, 98, 10, 50, 90, 45, 49, 9, 99, 94, 22, 24, 5, 85, 33, 3, 73, 35, 52, 63, 2, 76, 87, 43, 81, 83, 55, 61, 70, 75, 16, 14, 8, 71, 57, 40, 86, 39, 80, 79, 26, 48, 59, 4, 82, 0, 36, 12, 54, 38, 64, 17, 91, 27, 62, 84, 37, 74, 68, 1, 6, 19, 29, 46, 60, 30, 89, 15, 20, 97, 41, 31], [53, 22, 34, 16, 72, 71, 14, 94, 12, 59, 39, 6, 38, 68, 21, 93, 32, 46, 69, 55, 10, 8, 75, 60, 9, 13, 99, 90, 63, 49, 28, 92, 41, 7, 54, 83, 27, 91, 47, 43, 31, 74, 42, 40, 18, 81, 76, 84, 78, 52, 1, 26, 51, 2, 58, 11, 65, 67, 15, 23, 0, 79, 96, 4, 29, 62, 89, 66, 50, 98, 56, 61, 30, 88, 35, 25, 77, 70, 3, 44, 95, 80, 19, 64, 57, 37, 82, 85, 73, 48, 5, 86, 24, 36, 33, 97, 20, 45, 17, 87], [95, 36, 70, 82, 23, 55, 13, 51, 83, 38, 40, 18, 84, 74, 56, 85, 58, 14, 19, 69, 34, 59, 97, 89, 52, 77, 9, 91, 68, 16, 27, 88, 6, 73, 43, 5, 10, 66, 4, 61, 44, 46, 72, 50, 96, 21, 33, 15, 32, 0, 63, 92, 24, 39, 29, 49, 30, 64, 12, 26, 67, 53, 37, 2, 47, 65, 3, 20, 75, 78, 99, 87, 98, 1, 81, 90, 62, 54, 22, 35, 45, 25, 86, 48, 17, 60, 94, 8, 42, 31, 76, 28, 11, 57, 93, 41, 7, 71, 80, 79], [60, 24, 69, 92, 15, 36, 11, 98, 93, 27, 51, 35, 89, 74, 87, 4, 81, 94, 23, 84, 56, 3, 42, 18, 75, 73, 46, 86, 55, 99, 0, 88, 1, 26, 76, 70, 65, 67, 20, 13, 7, 45, 77, 17, 9, 78, 54, 48, 32, 40, 47, 31, 2, 6, 90, 10, 8, 50, 52, 38, 91, 14, 53, 12, 85, 44, 21, 80, 68, 33, 30, 57, 61, 63, 79, 41, 29, 39, 58, 5, 62, 96, 28, 71, 82, 34, 25, 43, 22, 95, 72, 37, 64, 16, 97, 59, 66, 83, 49, 19], [80, 0, 40, 36, 68, 18, 67, 14, 20, 21, 10, 17, 43, 3, 98, 81, 94, 55, 1, 39, 72, 51, 41, 66, 58, 2, 61, 78, 15, 99, 57, 52, 25, 87, 12, 65, 74, 64, 34, 37, 44, 30, 88, 79, 33, 27, 56, 35, 73, 42, 29, 54, 24, 5, 53, 16, 31, 4, 19, 84, 59, 50, 26, 63, 48, 28, 60, 45, 92, 82, 49, 77, 97, 76, 22, 86, 47, 62, 83, 70, 93, 38, 11, 13, 89, 75, 85, 69, 9, 46, 96, 90, 6, 91, 8, 7, 32, 71, 95, 23], [32, 14, 35, 84, 89, 11, 52, 34, 79, 65, 2, 88, 49, 29, 31, 94, 1, 74, 97, 51, 99, 37, 10, 47, 57, 81, 73, 76, 63, 58, 0, 38, 39, 27, 33, 8, 20, 21, 46, 66, 92, 36, 6, 30, 53, 17, 48, 64, 55, 28, 85, 50, 54, 12, 80, 41, 77, 69, 93, 9, 91, 13, 42, 75, 68, 86, 19, 3, 16, 78, 87, 45, 43, 56, 59, 70, 40, 24, 83, 98, 62, 5, 96, 4, 67, 60, 26, 23, 72, 95, 44, 82, 90, 25, 7, 18, 15, 22, 71, 61], [78, 53, 89, 93, 7, 84, 81, 95, 64, 50, 58, 35, 59, 63, 20, 76, 80, 8, 23, 28, 79, 52, 55, 48, 66, 17, 60, 65, 25, 29, 30, 9, 73, 39, 69, 3, 98, 22, 15, 87, 4, 37, 43, 5, 11, 83, 91, 40, 51, 33, 12, 92, 6, 67, 41, 94, 45, 88, 56, 36, 0, 68, 19, 54, 70, 26, 72, 77, 32, 34, 97, 71, 99, 75, 61, 31, 86, 82, 46, 2, 44, 96, 49, 74, 10, 62, 24, 16, 1, 38, 27, 14, 18, 85, 13, 57, 90, 21, 42, 47], [26, 30, 60, 78, 75, 48, 73, 52, 51, 57, 63, 90, 27, 36, 83, 81, 41, 44, 82, 37, 10, 64, 91, 4, 59, 95, 21, 24, 77, 56, 43, 38, 62, 55, 92, 0, 94, 20, 86, 66, 35, 80, 53, 25, 17, 18, 49, 76, 23, 89, 13, 15, 68, 8, 22, 46, 1, 42, 3, 34, 98, 88, 69, 31, 50, 65, 84, 32, 47, 61, 9, 19, 99, 85, 11, 79, 70, 2, 74, 14, 87, 7, 72, 5, 12, 58, 67, 39, 16, 71, 54, 6, 45, 93, 96, 28, 97, 29, 33, 40], [77, 66, 20, 30, 42, 23, 0, 49, 7, 64, 54, 27, 96, 97, 39, 84, 2, 51, 71, 17, 4, 92, 94, 95, 67, 69, 73, 75, 86, 37, 74, 50, 11, 79, 29, 15, 56, 43, 22, 83, 81, 61, 14, 3, 36, 44, 58, 10, 62, 19, 72, 80, 65, 24, 18, 5, 40, 90, 33, 9, 47, 76, 8, 59, 35, 91, 99, 13, 70, 88, 55, 16, 31, 28, 85, 45, 60, 25, 87, 82, 93, 12, 34, 68, 63, 26, 46, 48, 21, 52, 1, 78, 98, 38, 6, 32, 89, 53, 41, 57]], [[77, 99, 47, 64, 26, 63, 50, 81, 23, 45, 49, 36, 43, 56, 39, 12, 86, 62, 2, 98, 60, 94, 75, 9, 20, 74, 48, 28, 4, 84, 61, 31, 54, 15, 40, 7, 87, 38, 80, 6, 37, 46, 1, 55, 88, 73, 95, 33, 92, 18, 25, 66, 57, 27, 42, 35, 91, 51, 13, 90, 41, 83, 68, 53, 19, 3, 72, 89, 65, 70, 71, 8, 97, 59, 96, 52, 79, 22, 14, 69, 32, 93, 58, 29, 21, 76, 34, 5, 17, 67, 11, 78, 16, 0, 44, 30, 10, 24, 85, 82], [58, 62, 7, 39, 34, 69, 67, 73, 37, 59, 71, 66, 46, 57, 44, 51, 26, 85, 11, 28, 54, 47, 82, 21, 83, 76, 94, 16, 90, 95, 75, 55, 6, 22, 72, 74, 50, 40, 10, 19, 8, 53, 33, 98, 45, 87, 91, 13, 35, 70, 14, 38, 84, 99, 56, 30, 12, 89, 25, 97, 63, 65, 81, 92, 18, 29, 80, 61, 93, 43, 49, 52, 23, 31, 32, 4, 48, 3, 0, 78, 96, 64, 41, 88, 24, 5, 9, 15, 77, 86, 68, 1, 17, 79, 60, 36, 42, 2, 20, 27], [58, 62, 7, 39, 34, 69, 67, 73, 37, 59, 71, 66, 46, 57, 44, 51, 26, 85, 11, 28, 54, 47, 82, 21, 83, 76, 94, 16, 90, 95, 75, 55, 6, 22, 72, 74, 50, 40, 10, 19, 8, 53, 33, 98, 45, 87, 91, 13, 35, 70, 14, 38, 84, 99, 56, 30, 12, 89, 25, 97, 63, 65, 81, 92, 18, 29, 80, 61, 93, 43, 49, 52, 23, 31, 32, 4, 48, 3, 0, 78, 96, 64, 41, 88, 24, 5, 9, 15, 77, 86, 68, 1, 17, 79, 60, 36, 42, 2, 20, 27], [91, 43, 77, 69, 16, 96, 47, 34, 49, 15, 73, 84, 85, 22, 88, 95, 2, 80, 57, 33, 32, 41, 25, 14, 58, 9, 20, 65, 48, 97, 79, 89, 66, 63, 46, 83, 19, 92, 55, 18, 38, 0, 21, 50, 45, 62, 29, 26, 52, 28, 8, 6, 75, 86, 44, 81, 36, 90, 70, 30, 71, 39, 82, 87, 76, 1, 23, 5, 60, 98, 67, 53, 93, 72, 42, 74, 51, 4, 31, 59, 61, 7, 24, 56, 37, 54, 3, 11, 27, 40, 10, 64, 94, 35, 78, 68, 99, 17, 12, 13], [73, 70, 39, 9, 77, 61, 80, 10, 13, 92, 38, 4, 48, 57, 25, 72, 49, 51, 99, 97, 85, 36, 22, 15, 8, 34, 33, 76, 26, 45, 83, 59, 28, 96, 90, 47, 68, 88, 44, 6, 98, 12, 24, 46, 2, 54, 5, 58, 30, 63, 1, 18, 93, 67, 7, 50, 31, 16, 40, 56, 23, 86, 11, 52, 55, 75, 71, 27, 37, 87, 84, 65, 82, 29, 0, 14, 41, 35, 64, 21, 3, 95, 17, 60, 81, 74, 19, 91, 94, 32, 69, 53, 42, 89, 79, 43, 66, 20, 78, 62], [23, 78, 67, 41, 9, 77, 59, 72, 25, 82, 65, 89, 28, 37, 54, 70, 98, 33, 31, 44, 6, 17, 26, 73, 21, 36, 4, 2, 79, 95, 81, 50, 18, 34, 61, 0, 93, 24, 8, 66, 55, 62, 56, 30, 84, 58, 7, 88, 85, 64, 97, 39, 49, 3, 20, 42, 80, 96, 13, 63, 43, 60, 47, 90, 51, 14, 53, 1, 86, 57, 12, 19, 10, 45, 38, 68, 35, 87, 75, 5, 69, 27, 32, 91, 11, 99, 46, 29, 92, 22, 76, 15, 16, 48, 71, 74, 52, 94, 83, 40], [87, 89, 35, 98, 44, 21, 29, 83, 0, 77, 34, 60, 85, 64, 28, 58, 39, 36, 95, 22, 67, 30, 86, 57, 5, 81, 84, 26, 53, 62, 13, 90, 2, 88, 4, 46, 97, 73, 79, 43, 59, 72, 54, 32, 82, 10, 55, 38, 47, 12, 51, 1, 76, 48, 7, 14, 23, 20, 31, 18, 17, 15, 37, 42, 49, 68, 25, 93, 91, 40, 92, 50, 52, 70, 33, 80, 19, 96, 61, 75, 71, 99, 74, 9, 41, 66, 63, 8, 6, 24, 65, 56, 45, 69, 27, 16, 3, 78, 94, 11], [99, 6, 38, 11, 34, 28, 86, 57, 55, 78, 25, 95, 13, 63, 91, 14, 83, 1, 45, 17, 93, 76, 46, 79, 27, 85, 96, 58, 59, 44, 87, 65, 97, 22, 0, 51, 49, 52, 47, 67, 24, 88, 62, 50, 72, 3, 31, 82, 68, 42, 81, 23, 32, 98, 73, 60, 37, 54, 41, 80, 66, 18, 92, 4, 5, 94, 77, 39, 69, 16, 35, 7, 40, 30, 61, 26, 56, 64, 9, 71, 19, 21, 75, 84, 43, 53, 33, 29, 74, 36, 90, 2, 20, 15, 10, 48, 89, 70, 8, 12], [4, 28, 8, 72, 74, 31, 66, 0, 27, 54, 61, 23, 51, 73, 96, 32, 98, 41, 88, 95, 36, 22, 13, 38, 70, 84, 12, 7, 10, 60, 68, 33, 11, 35, 79, 42, 16, 62, 57, 24, 44, 94, 25, 48, 86, 97, 87, 49, 92, 71, 21, 1, 81, 5, 17, 85, 6, 75, 80, 34, 20, 30, 90, 69, 18, 89, 93, 56, 91, 40, 77, 52, 53, 14, 65, 45, 76, 2, 9, 29, 3, 26, 59, 55, 83, 46, 67, 47, 39, 50, 58, 63, 99, 15, 37, 43, 82, 64, 78, 19], [11, 94, 1, 93, 59, 91, 89, 51, 61, 81, 13, 29, 27, 58, 26, 3, 53, 69, 73, 21, 39, 12, 5, 18, 98, 74, 9, 96, 28, 65, 23, 4, 41, 72, 88, 34, 83, 54, 7, 15, 38, 84, 90, 52, 77, 48, 64, 60, 20, 79, 19, 66, 97, 30, 87, 45, 40, 36, 14, 86, 32, 33, 57, 16, 43, 42, 50, 10, 44, 76, 37, 6, 56, 31, 68, 99, 2, 17, 22, 35, 92, 85, 46, 75, 71, 67, 95, 78, 8, 63, 82, 25, 80, 24, 47, 49, 0, 70, 62, 55]], [[93, 99, 51, 49, 71, 64, 35, 42, 88, 17, 67, 92, 4, 12, 68, 13, 47, 7, 56, 14, 19, 53, 80, 85, 23, 5, 39, 6, 26, 89, 27, 54, 63, 73, 70, 33, 36, 3, 86, 58, 18, 2, 25, 21, 10, 34, 81, 94, 75, 98, 37, 46, 9, 95, 60, 74, 87, 78, 20, 24, 57, 0, 30, 83, 72, 61, 11, 32, 43, 82, 65, 69, 59, 62, 38, 76, 22, 16, 15, 45, 48, 79, 50, 90, 40, 1, 29, 77, 91, 31, 84, 96, 8, 52, 97, 41, 28, 44, 55, 66], [64, 71, 19, 27, 43, 95, 77, 16, 35, 81, 74, 29, 6, 86, 18, 37, 99, 46, 15, 87, 28, 63, 1, 65, 3, 79, 50, 12, 78, 84, 8, 88, 98, 69, 42, 0, 56, 32, 92, 83, 30, 59, 80, 9, 20, 89, 47, 23, 33, 34, 82, 24, 97, 60, 22, 90, 51, 76, 10, 94, 21, 91, 70, 49, 66, 14, 75, 2, 7, 13, 40, 93, 48, 36, 53, 72, 67, 62, 85, 17, 57, 58, 5, 25, 41, 31, 44, 73, 61, 26, 38, 54, 96, 39, 4, 68, 11, 52, 45, 55], [49, 88, 62, 73, 34, 15, 95, 68, 98, 5, 61, 35, 23, 45, 78, 64, 97, 70, 96, 65, 74, 16, 94, 37, 80, 56, 48, 28, 59, 1, 75, 4, 71, 47, 83, 93, 69, 21, 60, 38, 39, 19, 40, 82, 55, 7, 52, 18, 43, 54, 2, 77, 66, 90, 44, 32, 89, 3, 24, 6, 99, 17, 86, 29, 30, 22, 50, 81, 41, 42, 0, 9, 53, 58, 57, 25, 20, 12, 26, 51, 92, 87, 36, 31, 85, 63, 14, 8, 91, 11, 79, 27, 76, 84, 67, 33, 72, 13, 10, 46], [45, 15, 69, 88, 51, 28, 34, 80, 30, 42, 38, 90, 47, 17, 84, 49, 21, 55, 46, 96, 37, 97, 72, 85, 94, 29, 10, 66, 76, 82, 18, 86, 87, 25, 43, 92, 19, 89, 2, 93, 98, 40, 48, 53, 75, 99, 11, 62, 12, 60, 3, 24, 4, 6, 63, 81, 41, 20, 68, 9, 57, 52, 0, 44, 14, 16, 91, 27, 79, 73, 59, 61, 78, 7, 67, 1, 70, 83, 74, 64, 26, 95, 54, 65, 33, 39, 5, 50, 36, 35, 13, 23, 58, 71, 32, 77, 31, 22, 56, 8], [41, 43, 66, 69, 22, 23, 71, 2, 33, 38, 86, 51, 55, 59, 82, 96, 45, 97, 73, 34, 70, 21, 8, 58, 84, 90, 24, 25, 32, 78, 17, 27, 47, 68, 37, 72, 63, 77, 87, 89, 50, 16, 83, 54, 12, 56, 64, 62, 39, 92, 91, 53, 29, 76, 52, 94, 42, 81, 20, 98, 40, 79, 44, 10, 31, 0, 57, 19, 75, 67, 93, 6, 7, 11, 74, 26, 85, 5, 1, 49, 4, 61, 95, 3, 36, 9, 14, 13, 15, 48, 80, 46, 30, 65, 99, 18, 60, 88, 35, 28], [5, 56, 10, 81, 42, 35, 12, 94, 34, 13, 8, 0, 49, 17, 7, 69, 30, 1, 65, 14, 39, 2, 58, 76, 54, 31, 50, 46, 11, 27, 22, 61, 74, 64, 91, 18, 48, 63, 71, 57, 95, 87, 47, 67, 77, 53, 88, 23, 3, 83, 29, 86, 43, 60, 70, 78, 21, 99, 36, 66, 20, 62, 85, 4, 80, 98, 79, 82, 97, 15, 96, 52, 51, 6, 40, 93, 28, 41, 72, 45, 68, 16, 32, 75, 84, 89, 26, 55, 9, 59, 73, 24, 25, 33, 37, 19, 90, 44, 38, 92], [62, 28, 97, 69, 65, 46, 27, 96, 29, 73, 89, 42, 16, 36, 44, 63, 80, 60, 11, 54, 87, 92, 75, 81, 57, 26, 70, 49, 76, 10, 95, 84, 56, 22, 20, 9, 21, 61, 1, 47, 34, 19, 66, 0, 33, 91, 45, 3, 2, 90, 88, 43, 51, 12, 7, 18, 24, 85, 86, 8, 78, 38, 55, 30, 6, 35, 15, 93, 14, 99, 98, 82, 52, 74, 4, 50, 79, 37, 77, 17, 41, 71, 58, 53, 68, 39, 67, 25, 5, 83, 94, 13, 48, 32, 23, 59, 31, 64, 72, 40], [93, 20, 18, 22, 94, 27, 39, 59, 4, 11, 6, 75, 98, 62, 63, 81, 44, 53, 25, 95, 74, 57, 76, 5, 70, 60, 99, 12, 56, 85, 41, 67, 46, 19, 28, 1, 23, 80, 32, 68, 31, 51, 82, 55, 78, 77, 58, 69, 38, 87, 91, 79, 96, 52, 47, 73, 83, 89, 65, 3, 92, 14, 43, 66, 61, 37, 84, 54, 33, 88, 35, 71, 42, 90, 72, 50, 7, 40, 0, 24, 9, 29, 49, 45, 15, 21, 86, 64, 16, 36, 34, 17, 26, 10, 2, 13, 8, 97, 30, 48], [33, 3, 7, 64, 74, 23, 42, 25, 68, 85, 5, 8, 83, 17, 56, 79, 70, 73, 15, 6, 36, 18, 94, 97, 72, 22, 11, 96, 40, 58, 66, 49, 62, 86, 78, 67, 26, 98, 90, 48, 14, 2, 82, 91, 9, 76, 69, 44, 50, 47, 53, 71, 92, 12, 59, 37, 19, 60, 39, 13, 77, 16, 55, 41, 84, 31, 65, 27, 99, 51, 4, 45, 80, 46, 57, 21, 28, 81, 54, 29, 61, 88, 52, 43, 75, 20, 1, 10, 0, 35, 30, 32, 95, 38, 63, 87, 89, 24, 34, 93], [37, 25, 50, 66, 86, 23, 76, 27, 83, 97, 89, 35, 32, 41, 33, 87, 14, 59, 48, 61, 52, 3, 73, 67, 24, 56, 93, 22, 7, 70, 77, 28, 91, 30, 68, 29, 60, 8, 94, 13, 43, 17, 88, 57, 81, 34, 15, 95, 79, 96, 72, 84, 55, 46, 58, 10, 12, 38, 11, 99, 53, 42, 65, 44, 31, 21, 82, 6, 92, 26, 51, 5, 39, 63, 40, 9, 49, 18, 78, 80, 71, 74, 90, 2, 54, 47, 85, 75, 69, 45, 0, 16, 19, 1, 64, 98, 4, 62, 36, 20]]]; +var sbtable2 = [[3, 5, 8, 6, 0, 9, 7, 1, 2, 4], [1, 3, 9, 4, 2, 0, 8, 7, 5, 6], [0, 5, 1, 7, 9, 8, 6, 2, 3, 4], [6, 4, 7, 8, 3, 0, 9, 5, 2, 1], [2, 3, 8, 1, 9, 7, 6, 0, 4, 5], [3, 4, 1, 7, 2, 8, 6, 0, 9, 5], [6, 1, 8, 3, 0, 4, 2, 7, 5, 9], [9, 3, 7, 5, 2, 4, 0, 6, 1, 8], [6, 1, 5, 3, 0, 8, 7, 4, 2, 9], [9, 7, 4, 5, 1, 2, 3, 0, 8, 6]]; +var ibtable = [[[11, 38, 3, 63, 36, 39, 79, 19, 87, 68, 76, 51, 20, 56, 77, 61, 52, 73, 74, 94, 45, 31, 99, 28, 29, 90, 81, 96, 65, 75, 13, 32, 70, 21, 55, 33, 9, 15, 92, 14, 82, 97, 78, 37, 49, 0, 80, 57, 58, 7, 1, 89, 98, 53, 64, 5, 6, 66, 43, 83, 10, 50, 47, 84, 62, 71, 4, 67, 86, 42, 35, 34, 91, 12, 17, 69, 44, 48, 85, 30, 16, 95, 54, 23, 46, 18, 88, 59, 40, 60, 41, 25, 27, 22, 2, 24, 72, 93, 26, 8], [28, 58, 74, 34, 6, 14, 16, 46, 87, 24, 59, 57, 23, 88, 75, 65, 79, 38, 82, 13, 49, 99, 8, 94, 15, 19, 0, 96, 41, 95, 45, 35, 1, 91, 2, 52, 42, 76, 90, 84, 20, 54, 4, 63, 25, 5, 47, 85, 93, 12, 51, 81, 71, 69, 22, 17, 36, 64, 77, 80, 98, 53, 44, 18, 10, 68, 97, 61, 56, 70, 92, 27, 40, 9, 60, 7, 72, 21, 43, 3, 33, 32, 50, 26, 67, 62, 39, 48, 73, 86, 29, 89, 37, 78, 55, 66, 31, 30, 11, 83], [4, 16, 22, 66, 37, 14, 47, 89, 59, 60, 51, 92, 71, 70, 96, 13, 17, 85, 58, 93, 81, 69, 28, 90, 78, 39, 63, 88, 0, 75, 2, 53, 23, 99, 94, 68, 54, 74, 41, 29, 8, 26, 50, 98, 82, 95, 42, 7, 24, 77, 30, 9, 21, 1, 87, 62, 46, 15, 43, 38, 36, 55, 49, 57, 52, 56, 91, 65, 11, 84, 6, 73, 97, 33, 83, 27, 35, 25, 40, 32, 18, 31, 86, 48, 45, 3, 79, 76, 72, 64, 44, 20, 80, 19, 10, 5, 61, 34, 67, 12], [80, 91, 71, 26, 75, 8, 22, 92, 7, 70, 65, 51, 89, 31, 81, 30, 83, 47, 44, 85, 55, 19, 57, 87, 74, 6, 73, 40, 49, 32, 52, 78, 0, 12, 54, 15, 64, 28, 4, 24, 68, 17, 72, 53, 1, 94, 58, 88, 11, 82, 43, 86, 60, 63, 99, 96, 37, 77, 67, 33, 18, 5, 41, 59, 16, 36, 79, 97, 61, 23, 56, 48, 98, 38, 66, 21, 34, 29, 10, 3, 93, 46, 50, 39, 14, 9, 2, 13, 69, 42, 62, 35, 27, 90, 25, 76, 20, 95, 45, 84], [48, 16, 54, 47, 9, 39, 81, 91, 33, 53, 63, 21, 50, 85, 97, 90, 49, 36, 84, 74, 51, 76, 37, 67, 59, 58, 23, 20, 65, 82, 7, 77, 12, 31, 46, 1, 5, 14, 3, 30, 94, 95, 2, 34, 70, 89, 40, 87, 43, 79, 64, 57, 68, 26, 56, 44, 88, 61, 0, 24, 71, 18, 60, 4, 80, 96, 27, 15, 6, 13, 98, 29, 28, 25, 72, 93, 55, 75, 52, 66, 11, 8, 86, 45, 22, 83, 17, 10, 35, 38, 73, 99, 62, 41, 19, 69, 78, 92, 42, 32], [23, 19, 88, 44, 5, 39, 75, 81, 30, 14, 49, 54, 62, 55, 18, 83, 77, 76, 74, 92, 6, 95, 52, 36, 15, 27, 53, 38, 28, 50, 48, 99, 78, 67, 90, 87, 16, 41, 58, 65, 79, 11, 68, 84, 24, 97, 64, 47, 9, 22, 43, 86, 37, 8, 33, 17, 93, 61, 25, 72, 57, 98, 42, 80, 13, 89, 2, 12, 31, 56, 26, 85, 3, 29, 66, 63, 82, 10, 20, 94, 51, 0, 1, 4, 21, 60, 34, 35, 32, 45, 59, 71, 46, 69, 7, 96, 91, 40, 70, 73], [89, 62, 33, 19, 21, 97, 15, 2, 83, 22, 65, 30, 55, 7, 63, 73, 39, 61, 44, 37, 11, 26, 31, 79, 91, 0, 72, 68, 23, 87, 28, 24, 45, 74, 98, 14, 70, 54, 88, 42, 35, 59, 46, 16, 27, 92, 69, 66, 94, 32, 75, 77, 64, 57, 50, 71, 10, 3, 67, 81, 90, 58, 99, 5, 82, 85, 25, 52, 12, 8, 48, 49, 76, 96, 80, 20, 29, 34, 53, 51, 86, 93, 38, 84, 9, 36, 6, 60, 1, 78, 13, 95, 41, 17, 47, 18, 43, 40, 4, 56], [40, 68, 88, 47, 43, 28, 67, 23, 42, 99, 48, 3, 12, 27, 79, 25, 6, 55, 19, 80, 81, 62, 83, 69, 39, 73, 36, 30, 44, 82, 70, 52, 31, 34, 58, 74, 54, 2, 13, 45, 93, 49, 75, 72, 29, 87, 5, 7, 17, 76, 90, 63, 84, 51, 59, 35, 20, 97, 22, 65, 57, 66, 78, 86, 11, 9, 71, 98, 53, 56, 15, 46, 92, 0, 26, 21, 32, 38, 77, 91, 4, 24, 61, 85, 94, 1, 96, 64, 8, 41, 33, 50, 18, 60, 10, 16, 37, 95, 14, 89], [96, 23, 99, 42, 94, 91, 19, 53, 41, 25, 39, 73, 70, 72, 33, 35, 88, 2, 63, 49, 95, 60, 48, 97, 5, 54, 47, 40, 98, 18, 57, 28, 67, 92, 10, 79, 13, 76, 8, 55, 90, 62, 50, 87, 65, 82, 84, 21, 0, 14, 45, 44, 20, 38, 17, 3, 81, 16, 58, 4, 31, 29, 86, 15, 43, 64, 26, 52, 46, 69, 37, 68, 6, 22, 61, 7, 83, 71, 30, 75, 85, 78, 24, 27, 89, 9, 80, 34, 66, 77, 36, 93, 56, 59, 1, 12, 51, 32, 11, 74], [75, 99, 97, 8, 15, 48, 6, 25, 60, 90, 91, 95, 23, 3, 89, 77, 22, 78, 94, 55, 98, 35, 53, 96, 18, 52, 12, 16, 50, 20, 49, 9, 17, 13, 57, 44, 14, 47, 86, 56, 88, 41, 29, 32, 70, 1, 62, 37, 85, 38, 59, 36, 5, 68, 71, 69, 67, 27, 39, 4, 54, 0, 84, 45, 61, 73, 79, 93, 58, 66, 10, 76, 51, 92, 19, 87, 24, 7, 28, 2, 11, 80, 81, 33, 64, 74, 46, 65, 26, 72, 40, 82, 34, 42, 21, 83, 31, 30, 43, 63]], [[98, 58, 34, 65, 83, 74, 88, 5, 89, 46, 80, 43, 18, 87, 9, 28, 71, 90, 4, 36, 40, 11, 39, 31, 76, 92, 82, 48, 66, 41, 49, 99, 78, 79, 97, 86, 75, 68, 3, 7, 62, 64, 26, 22, 13, 77, 54, 50, 10, 96, 15, 35, 94, 73, 57, 93, 16, 61, 37, 38, 53, 2, 63, 23, 67, 72, 95, 70, 29, 33, 45, 47, 27, 24, 69, 44, 55, 85, 14, 8, 91, 12, 42, 6, 84, 81, 19, 25, 32, 51, 1, 17, 52, 56, 60, 0, 59, 30, 21, 20], [26, 63, 99, 57, 77, 53, 9, 75, 76, 80, 46, 97, 37, 14, 1, 12, 35, 20, 0, 15, 28, 19, 48, 41, 67, 30, 60, 69, 29, 34, 73, 10, 51, 47, 66, 82, 7, 98, 39, 96, 8, 62, 42, 3, 95, 5, 11, 13, 90, 94, 32, 31, 83, 64, 36, 88, 72, 52, 38, 54, 45, 17, 61, 81, 78, 44, 79, 55, 56, 86, 2, 40, 16, 24, 4, 71, 49, 33, 23, 92, 84, 74, 65, 43, 87, 59, 89, 68, 22, 70, 25, 58, 21, 85, 6, 50, 27, 93, 91, 18], [22, 31, 11, 72, 37, 70, 90, 60, 24, 56, 28, 69, 54, 85, 5, 98, 1, 76, 59, 20, 86, 32, 61, 49, 63, 42, 74, 53, 84, 3, 95, 23, 15, 36, 4, 81, 6, 21, 19, 27, 17, 83, 30, 45, 25, 65, 10, 50, 80, 66, 46, 75, 93, 82, 78, 99, 97, 68, 8, 13, 58, 94, 41, 14, 48, 52, 29, 79, 91, 89, 9, 55, 57, 2, 39, 92, 0, 44, 18, 62, 73, 96, 34, 88, 16, 77, 71, 43, 33, 40, 7, 12, 87, 51, 26, 47, 64, 35, 67, 38], [0, 80, 63, 52, 49, 69, 15, 87, 55, 60, 22, 91, 31, 89, 78, 28, 48, 12, 10, 42, 82, 23, 29, 18, 21, 2, 19, 7, 68, 37, 54, 90, 81, 43, 57, 94, 26, 95, 96, 88, 14, 51, 79, 71, 66, 76, 34, 24, 30, 9, 62, 44, 77, 65, 6, 27, 4, 97, 38, 36, 59, 3, 1, 50, 72, 46, 64, 35, 20, 11, 53, 13, 58, 39, 74, 8, 83, 75, 40, 98, 17, 99, 85, 32, 92, 67, 84, 5, 25, 56, 16, 47, 70, 93, 86, 61, 73, 41, 45, 33], [64, 57, 56, 7, 86, 9, 65, 16, 1, 63, 71, 26, 53, 98, 69, 5, 84, 28, 36, 58, 54, 99, 42, 74, 68, 3, 88, 22, 82, 97, 85, 45, 21, 66, 43, 59, 83, 51, 89, 87, 31, 12, 95, 52, 60, 17, 80, 27, 72, 93, 10, 39, 91, 30, 75, 61, 24, 8, 23, 2, 18, 73, 94, 6, 38, 44, 13, 40, 48, 4, 81, 37, 96, 46, 19, 49, 34, 50, 0, 20, 14, 15, 25, 92, 33, 29, 77, 90, 78, 67, 62, 41, 35, 47, 79, 32, 11, 70, 76, 55], [24, 99, 28, 52, 64, 3, 63, 16, 15, 87, 47, 6, 59, 98, 13, 78, 57, 81, 56, 94, 0, 37, 70, 73, 65, 83, 90, 92, 60, 82, 67, 40, 74, 34, 91, 2, 33, 85, 21, 54, 12, 31, 84, 55, 53, 49, 36, 25, 39, 20, 29, 93, 51, 76, 42, 96, 71, 86, 95, 66, 45, 19, 8, 58, 22, 69, 80, 79, 89, 17, 61, 18, 88, 38, 72, 75, 48, 30, 7, 10, 11, 35, 23, 9, 26, 4, 62, 44, 1, 43, 46, 14, 41, 77, 97, 27, 68, 32, 5, 50], [90, 80, 22, 27, 16, 23, 11, 31, 8, 75, 54, 82, 68, 66, 10, 40, 95, 99, 14, 42, 56, 88, 12, 55, 38, 6, 79, 84, 26, 92, 4, 67, 48, 5, 46, 77, 19, 53, 97, 34, 64, 73, 58, 47, 18, 39, 81, 59, 74, 62, 87, 98, 50, 1, 25, 9, 72, 69, 61, 60, 86, 3, 24, 28, 45, 30, 96, 36, 57, 83, 89, 63, 0, 33, 17, 7, 94, 15, 43, 2, 44, 41, 20, 85, 32, 65, 93, 49, 91, 52, 71, 37, 35, 13, 21, 51, 70, 29, 78, 76], [95, 50, 72, 0, 68, 98, 49, 53, 56, 41, 54, 22, 57, 78, 66, 31, 52, 29, 86, 30, 62, 26, 32, 46, 42, 48, 14, 21, 88, 94, 77, 92, 7, 63, 91, 28, 93, 38, 90, 71, 34, 25, 11, 83, 55, 70, 97, 82, 89, 76, 10, 99, 9, 45, 60, 39, 44, 16, 17, 37, 47, 79, 33, 36, 59, 8, 80, 23, 1, 18, 64, 51, 61, 81, 75, 40, 35, 73, 13, 65, 12, 4, 19, 85, 96, 6, 2, 58, 27, 43, 5, 87, 20, 15, 3, 24, 84, 67, 74, 69], [38, 33, 29, 88, 49, 47, 60, 69, 75, 12, 44, 89, 35, 45, 23, 30, 21, 28, 65, 86, 81, 40, 93, 97, 67, 2, 94, 9, 61, 92, 90, 32, 62, 36, 58, 51, 37, 73, 50, 63, 39, 43, 16, 71, 46, 91, 13, 7, 20, 72, 41, 59, 70, 48, 10, 52, 5, 34, 76, 15, 87, 6, 98, 18, 57, 77, 24, 79, 27, 19, 3, 0, 8, 95, 74, 64, 42, 4, 68, 31, 84, 54, 99, 25, 1, 80, 85, 26, 83, 11, 56, 55, 78, 66, 82, 14, 53, 22, 17, 96], [26, 12, 62, 5, 78, 53, 31, 46, 51, 8, 69, 80, 32, 68, 76, 42, 29, 87, 28, 75, 40, 91, 58, 7, 88, 92, 82, 96, 70, 50, 47, 65, 85, 3, 48, 73, 90, 89, 97, 84, 81, 39, 43, 79, 64, 54, 2, 41, 38, 10, 24, 22, 25, 93, 44, 23, 49, 37, 14, 95, 72, 74, 15, 11, 55, 98, 99, 0, 9, 16, 18, 20, 63, 30, 57, 19, 4, 17, 67, 35, 60, 45, 59, 56, 36, 77, 66, 33, 27, 71, 86, 1, 13, 34, 21, 61, 6, 94, 52, 83]], [[10, 87, 64, 11, 25, 97, 93, 18, 99, 38, 17, 72, 50, 23, 90, 57, 98, 12, 29, 46, 19, 77, 42, 15, 73, 52, 53, 89, 35, 20, 9, 41, 79, 13, 95, 48, 85, 54, 61, 94, 0, 74, 62, 40, 78, 68, 24, 28, 86, 21, 59, 14, 82, 84, 92, 58, 34, 31, 6, 16, 75, 81, 43, 47, 7, 3, 2, 37, 67, 8, 66, 22, 30, 32, 71, 44, 70, 1, 36, 26, 33, 63, 80, 83, 91, 76, 56, 39, 69, 55, 96, 60, 27, 49, 65, 88, 5, 4, 51, 45], [73, 87, 48, 43, 71, 40, 88, 23, 60, 35, 30, 5, 75, 25, 59, 95, 58, 79, 4, 89, 96, 17, 38, 6, 39, 9, 68, 81, 3, 90, 93, 99, 16, 42, 21, 45, 74, 84, 77, 65, 63, 98, 11, 51, 0, 33, 91, 22, 69, 34, 31, 20, 46, 2, 76, 54, 15, 62, 13, 70, 92, 55, 82, 47, 78, 7, 24, 27, 86, 1, 56, 61, 12, 44, 85, 57, 49, 19, 18, 67, 66, 52, 72, 53, 83, 41, 64, 50, 26, 94, 32, 80, 28, 10, 37, 14, 8, 97, 29, 36], [60, 50, 53, 78, 63, 90, 11, 33, 21, 24, 20, 55, 8, 25, 6, 58, 3, 98, 44, 82, 96, 14, 1, 59, 92, 75, 51, 36, 30, 64, 72, 40, 16, 94, 2, 74, 93, 85, 12, 10, 43, 32, 42, 39, 79, 97, 17, 38, 89, 29, 68, 52, 49, 0, 34, 19, 70, 84, 54, 9, 23, 71, 65, 28, 83, 56, 67, 57, 13, 18, 77, 5, 4, 88, 41, 22, 46, 76, 48, 61, 81, 45, 86, 35, 47, 87, 91, 99, 73, 66, 27, 37, 31, 15, 7, 80, 62, 95, 69, 26], [49, 73, 63, 66, 38, 35, 32, 96, 87, 26, 36, 92, 58, 6, 17, 47, 29, 84, 11, 18, 67, 45, 78, 4, 52, 81, 59, 30, 91, 54, 56, 89, 48, 46, 20, 79, 1, 62, 9, 53, 10, 95, 88, 34, 40, 80, 41, 64, 83, 55, 43, 7, 24, 61, 77, 5, 14, 93, 16, 21, 85, 39, 76, 50, 57, 65, 37, 60, 28, 19, 2, 97, 42, 33, 13, 68, 90, 25, 69, 99, 98, 74, 3, 8, 12, 15, 82, 71, 31, 23, 75, 27, 51, 94, 86, 0, 44, 22, 72, 70], [30, 32, 52, 21, 15, 79, 53, 40, 56, 44, 55, 6, 63, 39, 61, 4, 93, 43, 23, 99, 38, 66, 88, 18, 1, 86, 33, 9, 82, 76, 70, 51, 48, 69, 85, 11, 5, 91, 59, 77, 49, 75, 22, 87, 65, 41, 26, 50, 47, 98, 57, 10, 58, 62, 46, 28, 20, 71, 78, 95, 0, 72, 80, 73, 92, 36, 96, 37, 68, 2, 35, 83, 90, 25, 13, 24, 34, 42, 45, 74, 67, 16, 84, 97, 19, 64, 27, 14, 31, 12, 54, 60, 3, 8, 17, 89, 81, 94, 7, 29], [1, 18, 25, 13, 57, 53, 92, 95, 94, 88, 10, 82, 34, 83, 7, 28, 55, 11, 5, 58, 8, 9, 74, 99, 52, 32, 62, 45, 65, 50, 41, 56, 96, 44, 38, 47, 3, 39, 81, 19, 2, 22, 49, 12, 40, 67, 89, 76, 64, 70, 61, 21, 31, 54, 51, 17, 46, 30, 24, 60, 66, 26, 77, 63, 37, 35, 23, 6, 4, 87, 79, 97, 20, 48, 36, 85, 73, 71, 27, 43, 0, 15, 69, 78, 59, 86, 75, 33, 42, 84, 91, 93, 68, 80, 16, 98, 90, 72, 14, 29], [30, 16, 10, 67, 83, 81, 42, 94, 35, 59, 22, 5, 53, 61, 1, 96, 68, 45, 95, 66, 36, 37, 97, 87, 77, 93, 86, 33, 49, 13, 43, 14, 0, 34, 7, 2, 41, 21, 31, 32, 76, 55, 62, 72, 90, 71, 38, 23, 46, 12, 51, 19, 6, 44, 52, 48, 73, 24, 29, 74, 85, 99, 80, 28, 47, 9, 39, 84, 64, 57, 75, 98, 88, 26, 17, 63, 27, 56, 69, 8, 54, 25, 91, 78, 3, 50, 65, 70, 11, 4, 92, 60, 40, 58, 15, 89, 82, 18, 79, 20], [60, 88, 79, 35, 40, 43, 52, 4, 17, 31, 84, 44, 50, 94, 91, 38, 87, 25, 92, 62, 14, 97, 37, 18, 86, 28, 65, 90, 19, 29, 30, 75, 68, 49, 69, 11, 59, 41, 89, 33, 47, 54, 98, 42, 80, 56, 78, 99, 23, 82, 9, 48, 21, 1, 63, 22, 58, 95, 10, 12, 26, 74, 85, 13, 8, 27, 24, 53, 61, 34, 64, 71, 66, 32, 83, 73, 15, 67, 0, 20, 16, 6, 77, 45, 5, 93, 76, 39, 57, 2, 96, 46, 51, 3, 55, 7, 81, 70, 36, 72], [35, 56, 77, 58, 23, 83, 91, 81, 53, 70, 20, 74, 84, 50, 79, 51, 88, 44, 45, 71, 37, 26, 54, 48, 27, 43, 0, 12, 95, 97, 1, 63, 67, 98, 59, 40, 13, 19, 31, 87, 99, 16, 57, 30, 17, 92, 55, 68, 5, 46, 64, 8, 7, 42, 90, 33, 29, 9, 85, 24, 2, 69, 32, 10, 21, 65, 39, 86, 52, 62, 76, 89, 82, 6, 78, 4, 47, 28, 3, 75, 41, 15, 18, 14, 66, 73, 38, 80, 61, 49, 11, 22, 34, 93, 36, 25, 94, 96, 60, 72], [6, 90, 16, 43, 20, 55, 94, 8, 62, 59, 47, 32, 81, 67, 42, 35, 71, 19, 54, 49, 2, 88, 38, 5, 53, 77, 85, 11, 73, 34, 3, 72, 95, 58, 82, 64, 44, 29, 93, 14, 56, 98, 4, 37, 45, 75, 86, 60, 87, 7, 31, 17, 89, 97, 10, 70, 36, 99, 46, 63, 76, 41, 48, 84, 9, 52, 1, 24, 83, 25, 68, 18, 50, 26, 30, 27, 61, 0, 91, 33, 51, 40, 79, 39, 15, 74, 28, 78, 69, 96, 57, 65, 21, 80, 22, 23, 12, 13, 92, 66]], [[93, 42, 18, 65, 28, 87, 39, 35, 71, 23, 96, 90, 15, 58, 78, 33, 92, 88, 49, 64, 24, 84, 77, 8, 97, 50, 4, 53, 27, 83, 95, 31, 80, 47, 86, 55, 11, 40, 37, 14, 34, 60, 54, 12, 94, 9, 41, 2, 26, 10, 6, 57, 75, 63, 32, 43, 13, 52, 82, 73, 20, 30, 17, 5, 3, 68, 51, 89, 62, 79, 69, 70, 66, 45, 25, 22, 85, 0, 91, 76, 38, 7, 99, 61, 29, 98, 16, 36, 44, 67, 59, 56, 48, 81, 21, 46, 74, 72, 19, 1], [78, 91, 97, 77, 75, 85, 32, 2, 40, 86, 38, 18, 56, 47, 50, 87, 27, 92, 64, 39, 98, 23, 33, 72, 84, 58, 16, 99, 19, 65, 55, 73, 74, 42, 4, 48, 95, 8, 51, 3, 37, 82, 96, 69, 14, 44, 12, 21, 76, 70, 36, 15, 71, 41, 20, 31, 54, 13, 0, 9, 94, 67, 1, 60, 81, 61, 11, 6, 90, 5, 49, 10, 34, 7, 35, 30, 25, 88, 79, 93, 66, 62, 22, 24, 52, 17, 89, 45, 83, 57, 28, 46, 63, 68, 26, 29, 80, 59, 43, 53], [78, 91, 97, 77, 75, 85, 32, 2, 40, 86, 38, 18, 56, 47, 50, 87, 27, 92, 64, 39, 98, 23, 33, 72, 84, 58, 16, 99, 19, 65, 55, 73, 74, 42, 4, 48, 95, 8, 51, 3, 37, 82, 96, 69, 14, 44, 12, 21, 76, 70, 36, 15, 71, 41, 20, 31, 54, 13, 0, 9, 94, 67, 1, 60, 81, 61, 11, 6, 90, 5, 49, 10, 34, 7, 35, 30, 25, 88, 79, 93, 66, 62, 22, 24, 52, 17, 89, 45, 83, 57, 28, 46, 63, 68, 26, 29, 80, 59, 43, 53], [41, 65, 16, 86, 77, 67, 51, 81, 50, 25, 90, 87, 98, 99, 23, 9, 4, 97, 39, 36, 26, 42, 13, 66, 82, 22, 47, 88, 49, 46, 59, 78, 20, 19, 7, 93, 56, 84, 40, 61, 89, 21, 74, 1, 54, 44, 34, 6, 28, 8, 43, 76, 48, 71, 85, 38, 83, 18, 24, 79, 68, 80, 45, 33, 91, 27, 32, 70, 95, 3, 58, 60, 73, 10, 75, 52, 64, 2, 94, 30, 17, 55, 62, 35, 11, 12, 53, 63, 14, 31, 57, 0, 37, 72, 92, 15, 5, 29, 69, 96], [74, 50, 44, 80, 11, 46, 39, 54, 24, 3, 7, 62, 41, 8, 75, 23, 57, 82, 51, 86, 97, 79, 22, 60, 42, 14, 28, 67, 32, 73, 48, 56, 89, 26, 25, 77, 21, 68, 10, 2, 58, 76, 92, 95, 38, 29, 43, 35, 12, 16, 55, 17, 63, 91, 45, 64, 59, 13, 47, 31, 83, 5, 99, 49, 78, 71, 96, 53, 36, 90, 1, 66, 15, 0, 85, 65, 27, 4, 98, 94, 6, 84, 72, 30, 70, 20, 61, 69, 37, 93, 34, 87, 9, 52, 88, 81, 33, 19, 40, 18], [35, 67, 27, 53, 26, 79, 20, 46, 38, 4, 72, 84, 70, 58, 65, 91, 92, 21, 32, 71, 54, 24, 89, 0, 37, 8, 22, 81, 12, 87, 43, 18, 82, 17, 33, 76, 25, 13, 74, 51, 99, 3, 55, 60, 19, 73, 86, 62, 93, 52, 31, 64, 96, 66, 14, 40, 42, 69, 45, 6, 61, 34, 41, 59, 49, 10, 39, 2, 75, 80, 15, 94, 7, 23, 95, 78, 90, 5, 1, 28, 56, 30, 9, 98, 44, 48, 68, 77, 47, 11, 63, 83, 88, 36, 97, 29, 57, 50, 16, 85], [8, 51, 32, 96, 34, 24, 88, 54, 87, 83, 45, 99, 49, 30, 55, 61, 95, 60, 59, 76, 57, 5, 19, 56, 89, 66, 27, 94, 14, 6, 21, 58, 43, 74, 10, 2, 17, 62, 47, 16, 69, 84, 63, 39, 4, 92, 35, 48, 53, 64, 71, 50, 72, 28, 42, 46, 91, 23, 15, 40, 11, 78, 29, 86, 13, 90, 85, 20, 65, 93, 73, 80, 41, 37, 82, 79, 52, 9, 97, 38, 75, 25, 44, 7, 26, 12, 22, 0, 33, 1, 31, 68, 70, 67, 98, 18, 77, 36, 3, 81], [34, 17, 91, 45, 63, 64, 1, 71, 98, 78, 94, 3, 99, 12, 15, 93, 69, 19, 61, 80, 92, 81, 33, 51, 40, 10, 75, 24, 5, 87, 73, 46, 52, 86, 4, 70, 89, 56, 2, 67, 72, 58, 49, 84, 29, 18, 22, 38, 95, 36, 43, 35, 37, 85, 57, 8, 76, 7, 27, 28, 55, 74, 42, 13, 77, 31, 60, 39, 48, 68, 97, 79, 44, 54, 88, 82, 21, 66, 9, 23, 59, 50, 47, 16, 83, 25, 6, 30, 41, 96, 90, 14, 62, 20, 65, 11, 26, 32, 53, 0], [7, 51, 77, 80, 0, 53, 56, 27, 2, 78, 28, 32, 26, 22, 73, 93, 36, 54, 64, 99, 60, 50, 21, 11, 39, 42, 81, 8, 1, 79, 61, 5, 15, 31, 59, 33, 20, 94, 23, 88, 69, 17, 35, 95, 40, 75, 85, 87, 43, 47, 89, 12, 71, 72, 9, 83, 67, 38, 90, 82, 29, 10, 37, 91, 97, 74, 6, 86, 30, 63, 24, 49, 3, 13, 4, 57, 76, 70, 98, 34, 58, 52, 96, 84, 25, 55, 44, 46, 18, 65, 62, 68, 48, 66, 41, 19, 14, 45, 16, 92], [96, 2, 76, 15, 31, 22, 71, 38, 88, 26, 67, 0, 21, 10, 58, 39, 63, 77, 23, 50, 48, 19, 78, 30, 93, 91, 14, 12, 28, 11, 53, 73, 60, 61, 35, 79, 57, 70, 40, 20, 56, 32, 65, 64, 68, 55, 82, 94, 45, 95, 66, 7, 43, 16, 37, 99, 72, 62, 13, 4, 47, 8, 98, 89, 46, 29, 51, 85, 74, 17, 97, 84, 33, 18, 25, 83, 69, 44, 87, 49, 92, 9, 90, 36, 41, 81, 59, 54, 34, 6, 42, 5, 80, 3, 1, 86, 27, 52, 24, 75]], [[61, 85, 41, 37, 12, 25, 27, 17, 92, 52, 44, 66, 13, 15, 19, 78, 77, 9, 40, 20, 58, 43, 76, 24, 59, 42, 28, 30, 96, 86, 62, 89, 67, 35, 45, 6, 36, 50, 74, 26, 84, 95, 7, 68, 97, 79, 51, 16, 80, 3, 82, 2, 93, 21, 31, 98, 18, 60, 39, 72, 54, 65, 73, 32, 5, 70, 99, 10, 14, 71, 34, 4, 64, 33, 55, 48, 75, 87, 57, 81, 22, 46, 69, 63, 90, 23, 38, 56, 8, 29, 83, 88, 11, 0, 47, 53, 91, 94, 49, 1], [35, 22, 67, 24, 94, 82, 12, 68, 30, 43, 58, 96, 27, 69, 65, 18, 7, 79, 14, 2, 44, 60, 54, 47, 51, 83, 89, 3, 20, 11, 40, 85, 37, 48, 49, 8, 73, 15, 90, 93, 70, 84, 34, 4, 86, 98, 17, 46, 72, 63, 26, 56, 97, 74, 91, 99, 36, 80, 81, 41, 53, 88, 77, 21, 0, 23, 64, 76, 95, 33, 62, 1, 75, 87, 10, 66, 57, 6, 28, 25, 42, 9, 50, 39, 29, 78, 13, 19, 31, 45, 55, 61, 38, 71, 59, 5, 92, 52, 32, 16], [70, 29, 50, 57, 31, 9, 59, 45, 87, 71, 98, 89, 77, 97, 86, 5, 21, 61, 47, 41, 76, 37, 65, 12, 58, 75, 78, 91, 27, 63, 64, 83, 55, 95, 4, 11, 82, 23, 39, 40, 42, 68, 69, 48, 54, 13, 99, 33, 26, 0, 66, 79, 46, 72, 49, 44, 25, 74, 73, 28, 38, 10, 2, 85, 15, 19, 52, 94, 7, 36, 17, 32, 96, 3, 20, 30, 92, 51, 14, 90, 24, 67, 43, 34, 93, 84, 62, 81, 1, 56, 53, 88, 80, 35, 22, 6, 18, 16, 8, 60], [62, 75, 38, 50, 52, 86, 53, 73, 99, 59, 26, 46, 48, 90, 64, 1, 65, 13, 30, 36, 57, 16, 97, 91, 51, 33, 80, 67, 5, 25, 8, 96, 94, 84, 6, 89, 88, 20, 10, 85, 41, 56, 9, 34, 63, 0, 18, 12, 42, 15, 87, 4, 61, 43, 82, 17, 98, 60, 92, 70, 49, 71, 47, 54, 79, 83, 27, 74, 58, 2, 76, 93, 22, 69, 78, 44, 28, 95, 72, 68, 7, 55, 29, 77, 14, 23, 31, 32, 3, 37, 11, 66, 35, 39, 24, 81, 19, 21, 40, 45], [65, 78, 7, 83, 80, 77, 71, 72, 22, 85, 63, 73, 44, 87, 86, 88, 41, 30, 95, 67, 58, 21, 4, 5, 26, 27, 75, 31, 99, 52, 92, 64, 28, 8, 19, 98, 84, 34, 9, 48, 60, 0, 56, 1, 62, 16, 91, 32, 89, 79, 40, 11, 54, 51, 43, 12, 45, 66, 23, 13, 96, 81, 47, 36, 46, 93, 2, 69, 33, 3, 20, 6, 35, 18, 74, 68, 53, 37, 29, 61, 90, 57, 14, 42, 24, 76, 10, 38, 97, 39, 25, 50, 49, 70, 55, 82, 15, 17, 59, 94], [11, 17, 21, 48, 63, 0, 73, 14, 10, 88, 2, 28, 6, 9, 19, 69, 81, 13, 35, 95, 60, 56, 30, 47, 91, 92, 86, 29, 76, 50, 16, 25, 82, 93, 8, 5, 58, 94, 98, 20, 74, 77, 4, 52, 97, 79, 27, 42, 36, 12, 26, 72, 71, 45, 24, 87, 1, 39, 22, 89, 53, 31, 61, 37, 33, 18, 59, 43, 80, 15, 54, 38, 78, 90, 32, 83, 23, 44, 55, 66, 64, 3, 67, 49, 84, 62, 51, 41, 46, 85, 96, 34, 99, 75, 7, 40, 70, 68, 65, 57], [43, 38, 48, 47, 74, 88, 64, 54, 59, 35, 29, 18, 53, 91, 68, 66, 12, 79, 55, 41, 34, 36, 33, 94, 56, 87, 25, 6, 1, 8, 63, 96, 93, 44, 40, 65, 13, 77, 61, 85, 99, 80, 11, 51, 14, 46, 5, 39, 92, 27, 75, 52, 72, 83, 19, 62, 32, 24, 82, 95, 17, 37, 0, 15, 97, 4, 42, 86, 84, 3, 26, 81, 98, 9, 73, 22, 28, 78, 60, 76, 16, 23, 71, 89, 31, 57, 58, 20, 50, 10, 49, 45, 21, 67, 90, 30, 7, 2, 70, 69], [78, 35, 94, 59, 8, 23, 10, 76, 96, 80, 93, 9, 27, 95, 61, 84, 88, 91, 2, 33, 1, 85, 3, 36, 79, 18, 92, 5, 34, 81, 98, 40, 38, 68, 90, 70, 89, 65, 48, 6, 77, 30, 72, 62, 16, 83, 32, 54, 99, 82, 75, 41, 53, 17, 67, 43, 28, 21, 46, 7, 25, 64, 13, 14, 87, 58, 63, 31, 39, 47, 24, 71, 74, 55, 20, 11, 22, 45, 44, 51, 37, 15, 42, 56, 66, 29, 86, 49, 69, 57, 73, 50, 60, 0, 4, 19, 52, 97, 12, 26], [88, 86, 41, 1, 70, 10, 19, 2, 11, 44, 87, 26, 53, 59, 40, 18, 61, 13, 21, 56, 85, 75, 25, 5, 97, 7, 36, 67, 76, 79, 90, 65, 91, 0, 98, 89, 20, 55, 93, 58, 28, 63, 6, 83, 47, 71, 73, 49, 39, 31, 48, 69, 82, 50, 78, 62, 14, 74, 29, 54, 57, 80, 32, 94, 3, 66, 30, 35, 8, 46, 16, 51, 24, 17, 4, 84, 45, 60, 34, 15, 72, 77, 42, 12, 64, 9, 33, 95, 81, 96, 38, 43, 52, 99, 22, 92, 27, 23, 37, 68], [90, 93, 83, 21, 96, 71, 67, 28, 37, 75, 55, 58, 56, 39, 16, 46, 91, 41, 77, 92, 99, 65, 27, 5, 24, 1, 69, 7, 31, 35, 33, 64, 12, 14, 45, 11, 98, 0, 57, 72, 74, 13, 61, 40, 63, 89, 53, 85, 18, 76, 2, 70, 20, 60, 84, 52, 25, 43, 54, 17, 36, 19, 97, 73, 94, 62, 3, 23, 34, 88, 29, 80, 50, 22, 81, 87, 6, 30, 78, 48, 79, 44, 66, 8, 51, 86, 4, 15, 42, 10, 82, 32, 68, 26, 38, 47, 49, 9, 95, 59]]]; +var ibtable2 = [[4, 7, 8, 0, 9, 1, 3, 6, 2, 5], [5, 0, 4, 1, 3, 8, 9, 7, 6, 2], [0, 2, 7, 8, 9, 1, 6, 3, 5, 4], [5, 9, 8, 4, 1, 7, 0, 2, 3, 6], [7, 3, 0, 1, 8, 9, 6, 5, 2, 4], [7, 2, 4, 0, 1, 9, 6, 3, 5, 8], [4, 1, 6, 3, 5, 8, 0, 7, 2, 9], [6, 8, 4, 1, 5, 3, 7, 2, 9, 0], [4, 1, 8, 3, 7, 2, 0, 6, 5, 9], [7, 4, 5, 6, 2, 3, 9, 1, 8, 0]]; +function crc16(data, bits, initial = 65535, poly = 33800) { + let v = (0, import_big_integer.default)(initial); + let bigPoly = (0, import_big_integer.default)(poly); + for (let i = 0; i < bits; i++) { + v = v.shiftRight(1).xor(bigPoly.and(v.xor(data).and(import_big_integer.default.one).equals(import_big_integer.default.one) ? bigPoly : import_big_integer.default.zero)); + data = data.shiftRight(1); + } + return v.toJSNumber(); +} +function decodeAccessCode(code) { + code = code.replace(/\D/i, ""); + if (code.length !== 20) { + return null; + } + let body = import_lodash.default.range(3, 15, 2).map((i) => parseInt(code[i]) * 10 + parseInt(code[i + 1])); + let crc = import_lodash.default.range(15, 20).map((i) => parseInt(code[i])); + let boxes = [(crc[3] + crc[2]) % 10, crc[2], crc[3], crc[4], (crc[4] + crc[0]) % 10, crc[1]]; + for (const [n, i] of body.entries()) { + body[n] = ibtable[4][boxes[n]][i]; + } + const rv = body[0] >> 4; + boxes = [(crc[1] + crc[0]) % 10, crc[1], crc[2], crc[3], crc[4], (crc[4] + crc[1]) % 10]; + for (const [n, i] of body.entries()) { + if (n == 0) { + body[n] = body[n] & 240 | ibtable2[boxes[n]][body[n] & 15]; + } else { + body[n] = ibtable[rv][boxes[n]][i]; + } + } + const serial = body.map((i) => i.toString().padStart(2, "0")).join(""); + if (crc16((0, import_big_integer.default)(code.substring(0, 3) + serial, 16), 15 * 4) !== parseInt(code.substring(15, 20))) { + throw new Error(`CRC16 mismatch.`); + } + return { revision: rv, serial: parseInt(serial) }; +} +function encodeAccessCode(company, serial, rev = 0) { + if (company < 0 || company > 999) { + throw new Error(`Invalid company code`); + } + if (serial < 0 || serial > 99999999999) { + throw new Error(`Invalid serial number`); + } + if (rev < 0 || rev > sbtable.length) { + throw new Error(`Invalid revision`); + } + const bodyStr = `${rev}${serial.toString().padStart(11, "0")}`; + const crc_i = crc16((0, import_big_integer.default)(company.toString().padStart(3, "0") + bodyStr, 16), 15 * 4); + const crc = import_lodash.default.range(5).map((i) => Math.floor(crc_i / 10 ** (4 - i)) % 10); + const body = import_lodash.default.range(0, 12, 2).map((i) => parseInt(bodyStr[i]) * 10 + parseInt(bodyStr[i + 1])); + let boxes = [(crc[1] + crc[0]) % 10, crc[1], crc[2], crc[3], crc[4], (crc[4] + crc[1]) % 10]; + for (const [n, i] of body.entries()) { + if (n == 0) { + body[n] = body[n] & 240 | sbtable2[boxes[n]][body[n] & 15]; + } else { + body[n] = sbtable[rev][boxes[n]][i]; + } + } + boxes = [(crc[3] + crc[2]) % 10, crc[2], crc[3], crc[4], (crc[4] + crc[0]) % 10, crc[1]]; + for (const [n, i] of body.entries()) { + body[n] = sbtable[4][boxes[n]][i]; + } + return `${company.toString().padStart(3, "0")}${body.map((i) => i.toString().padStart(2, "0")).join("")}${crc_i.toString().padStart(5, "0")}`; } // src/card.ts var CARD_ID_REGEX = /^(?:[0-9]{4} ?){5}$/i; +var AMNET_COMPANY_ID = 597; function generateCardNumber() { - let cardId = ""; - while (true) { - const firstDigit = Math.floor(Math.random() * 10); - if (firstDigit !== 3) { - cardId = firstDigit.toString(); - break; - } - } - for (let i = 0; i < 19; i++) { - cardId += Math.floor(Math.random() * 10).toString(); - } - return cardId; + const serial = Math.floor(Math.random() * 1e11); + return encodeAccessCode(AMNET_COMPANY_ID, serial, 0); } function validateCardId(id) { return id[0] !== "3" && CARD_ID_REGEX.test(id); @@ -150,7 +201,10 @@ function getGameName(id) { // Annotate the CommonJS export names for ESM import in node: 0 && (module.exports = { AMNET_API_VERSION, + AMNET_COMPANY_ID, CARD_ID_REGEX, + DecodeAMAccessCode, + EncodeAMAccessCode, MIN_AMNET_API_VERSION, fetchServerInfo, generateCardNumber, diff --git a/amnet-shared/dist/index.js.map b/amnet-shared/dist/index.js.map index 8db7e48..642da6b 100644 --- a/amnet-shared/dist/index.js.map +++ b/amnet-shared/dist/index.js.map @@ -1 +1 @@ -{"version":3,"sources":["../src/index.ts","../src/api.ts","../src/card.ts","../src/gameIds.ts"],"sourcesContent":["export * from './api';\nexport * from './card';\nexport * from './gameIds';","/**\n * The latest version of the AMNet API this library supports\n */\nexport const AMNET_API_VERSION = 1;\n\n/**\n * The minimum version of the AMNet API this library supports\n */\nexport const MIN_AMNET_API_VERSION = 1;\n\nexport interface AMCardInRequest {\n cardId: string;\n}\n\n/**\n * Server connection info (api version, address, etc.)\n */\nexport interface AMServerConnectionInfo {\n apiVersion: number;\n serverAddress: string;\n}\n\n/**\n * User-definable server metadata\n */\nexport interface AMServerMetadata {\n serverName: string;\n gameId?: string | null | undefined;\n}\n\n/**\n * Metrics about the current game session\n */\nexport interface AMServerInstanceMetrics {\n timeSinceLastPoll?: number;\n sessionUptime?: number;\n}\n\n/**\n * The response from an AMNet server's info endpoint\n */\nexport type AMServerInfo = AMServerMetadata & AMServerConnectionInfo & AMServerInstanceMetrics;\n\n/**\n * Performs the card-in request to the specified server\n * @param server The server to perform the request against\n * @param request The card-in request to send\n * @param signal The abort signal to use for the request\n */\nexport async function performCardIn(server: AMServerConnectionInfo, request: AMCardInRequest, signal: AbortSignal): Promise {\n if (server.apiVersion < MIN_AMNET_API_VERSION || server.apiVersion > AMNET_API_VERSION) {\n throw new Error(\"Unsupported server API version\");\n }\n \n try {\n const response = await fetch(`${new URL(server.serverAddress).origin}/amnet/signin`, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\"\n },\n body: JSON.stringify(request),\n signal: signal\n });\n\n return response.ok;\n } catch {\n return false;\n }\n}\n\n/**\n * Attempts to connect to the specified server and fetch its info\n * @param serverAddress The origin address of the server to connect to\n * @param abort The abort signal to use for the request (for cancellation)\n */\nexport async function fetchServerInfo(serverAddress: string, abort: AbortSignal): Promise {\n try {\n const response = await fetch(`${new URL(serverAddress).origin}/amnet/info`, {\n signal: abort\n });\n \n if (!response.ok) {\n return null;\n }\n\n return {\n ...await response.json(),\n serverAddress: serverAddress\n } satisfies AMServerMetadata;\n } catch {\n return null;\n }\n}\n","export const CARD_ID_REGEX = /^(?:[0-9]{4} ?){5}$/i;\n\nexport function generateCardNumber(): string {\n let cardId = '';\n\n while (true) {\n // don't start with a 3\n const firstDigit = Math.floor(Math.random() * 10);\n\n if (firstDigit !== 3) {\n cardId = firstDigit.toString();\n break;\n }\n }\n\n for (let i = 0; i < 19; i++) {\n cardId += Math.floor(Math.random() * 10).toString();\n }\n\n return cardId;\n}\n\n/**\n * Validates the provided card id by known parameters\n * @param id The card id to validate\n */\nexport function validateCardId(id: string): boolean {\n return id[0] !== '3' && CARD_ID_REGEX.test(id);\n}\n","/**\n * Get the game name from the game identifier (4-letter code)\n * @param id\n */\nexport function getGameName(id: string): string | null {\n switch (id?.toUpperCase()) {\n case \"SDGT\":\n return \"Initial D The Arcade\";\n case \"SDHD\":\n case \"SDBT\":\n return \"CHUNITHM\";\n case \"SDDT\":\n return \"O.N.G.E.K.I.\";\n case \"SDEZ\":\n return \"maimai DX\";\n case \"SBZV\":\n return \"Project DIVA Future Tone\";\n \n default:\n return null;\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACGO,IAAM,oBAAoB;AAK1B,IAAM,wBAAwB;AAyCrC,SAAsB,cAAc,QAAgC,SAA0B,QAAuC;AAAA;AACjI,QAAI,OAAO,aAAa,yBAAyB,OAAO,aAAa,mBAAmB;AACpF,YAAM,IAAI,MAAM,gCAAgC;AAAA,IACpD;AAEA,QAAI;AACA,YAAM,WAAW,MAAM,MAAM,GAAG,IAAI,IAAI,OAAO,aAAa,EAAE,MAAM,iBAAiB;AAAA,QACjF,QAAQ;AAAA,QACR,SAAS;AAAA,UACL,gBAAgB;AAAA,QACpB;AAAA,QACA,MAAM,KAAK,UAAU,OAAO;AAAA,QAC5B;AAAA,MACJ,CAAC;AAED,aAAO,SAAS;AAAA,IACpB,SAAQ;AACJ,aAAO;AAAA,IACX;AAAA,EACJ;AAAA;AAOA,SAAsB,gBAAgB,eAAuB,OAAkD;AAAA;AAC3G,QAAI;AACA,YAAM,WAAW,MAAM,MAAM,GAAG,IAAI,IAAI,aAAa,EAAE,MAAM,eAAe;AAAA,QACxE,QAAQ;AAAA,MACZ,CAAC;AAED,UAAI,CAAC,SAAS,IAAI;AACd,eAAO;AAAA,MACX;AAEA,aAAO,iCACA,MAAM,SAAS,KAAK,IADpB;AAAA,QAEH;AAAA,MACJ;AAAA,IACJ,SAAQ;AACJ,aAAO;AAAA,IACX;AAAA,EACJ;AAAA;;;AC5FO,IAAM,gBAAgB;AAEtB,SAAS,qBAA6B;AACzC,MAAI,SAAS;AAEb,SAAO,MAAM;AAET,UAAM,aAAa,KAAK,MAAM,KAAK,OAAO,IAAI,EAAE;AAEhD,QAAI,eAAe,GAAG;AAClB,eAAS,WAAW,SAAS;AAC7B;AAAA,IACJ;AAAA,EACJ;AAEA,WAAS,IAAI,GAAG,IAAI,IAAI,KAAK;AACzB,cAAU,KAAK,MAAM,KAAK,OAAO,IAAI,EAAE,EAAE,SAAS;AAAA,EACtD;AAEA,SAAO;AACX;AAMO,SAAS,eAAe,IAAqB;AAChD,SAAO,GAAG,CAAC,MAAM,OAAO,cAAc,KAAK,EAAE;AACjD;;;ACxBO,SAAS,YAAY,IAA2B;AACnD,UAAQ,yBAAI,eAAe;AAAA,IACvB,KAAK;AACD,aAAO;AAAA,IACX,KAAK;AAAA,IACL,KAAK;AACD,aAAO;AAAA,IACX,KAAK;AACD,aAAO;AAAA,IACX,KAAK;AACD,aAAO;AAAA,IACX,KAAK;AACD,aAAO;AAAA,IAEX;AACI,aAAO;AAAA,EACf;AACJ;","names":[]} \ No newline at end of file +{"version":3,"sources":["../src/index.ts","../src/api.ts","../src/card-encoding.ts","../src/card.ts","../src/gameIds.ts"],"sourcesContent":["export * from './api';\nexport * from './card';\nexport * from './gameIds';\n\nexport {decodeAccessCode as DecodeAMAccessCode, encodeAccessCode as EncodeAMAccessCode} from './card-encoding';","/**\n * The latest version of the AMNet API this library supports\n */\nexport const AMNET_API_VERSION = 1;\n\n/**\n * The minimum version of the AMNet API this library supports\n */\nexport const MIN_AMNET_API_VERSION = 1;\n\nexport interface AMCardInRequest {\n cardId: string;\n physicalCardIDm?: string;\n}\n\n/**\n * Server connection info (api version, address, etc.)\n */\nexport interface AMServerConnectionInfo {\n apiVersion: number;\n serverAddress: string;\n}\n\n/**\n * User-definable server metadata\n */\nexport interface AMServerMetadata {\n serverName: string;\n gameId?: string | null | undefined;\n}\n\n/**\n * Metrics about the current game session\n */\nexport interface AMServerInstanceMetrics {\n timeSinceLastPoll?: number;\n sessionUptime?: number;\n}\n\n/**\n * The response from an AMNet server's info endpoint\n */\nexport type AMServerInfo = AMServerMetadata & AMServerConnectionInfo & AMServerInstanceMetrics;\n\n/**\n * Performs the card-in request to the specified server\n * @param server The server to perform the request against\n * @param request The card-in request to send\n * @param signal The abort signal to use for the request\n */\nexport async function performCardIn(server: AMServerConnectionInfo, request: AMCardInRequest, signal: AbortSignal): Promise {\n if (server.apiVersion < MIN_AMNET_API_VERSION || server.apiVersion > AMNET_API_VERSION) {\n throw new Error(\"Unsupported server API version\");\n }\n\n try {\n const response = await fetch(`${new URL(server.serverAddress).origin}/amnet/signin`, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\"\n },\n body: JSON.stringify(request),\n signal: signal\n });\n\n return response.ok;\n } catch {\n return false;\n }\n}\n\n/**\n * Attempts to connect to the specified server and fetch its info\n * @param serverAddress The origin address of the server to connect to\n * @param abort The abort signal to use for the request (for cancellation)\n */\nexport async function fetchServerInfo(serverAddress: string, abort: AbortSignal): Promise {\n try {\n const response = await fetch(`${new URL(serverAddress).origin}/amnet/info`, {\n signal: abort\n });\n\n if (!response.ok) {\n return null;\n }\n\n return {\n ...await response.json(),\n serverAddress: serverAddress\n } satisfies AMServerMetadata;\n } catch {\n return null;\n }\n}\n","import _ from \"lodash\";\nimport bigInt, {BigInteger} from \"big-integer\";\n\nconst sbtable = [[[45, 50, 94, 2, 66, 55, 56, 49, 99, 36, 60, 0, 73, 30, 39, 37, 80, 74, 85, 7, 12, 33, 93, 83, 95, 91, 98, 92, 23, 24, 79, 21, 31, 35, 71, 70, 4, 43, 1, 5, 88, 90, 69, 58, 76, 20, 84, 62, 77, 44, 61, 11, 16, 53, 82, 34, 13, 47, 48, 87, 89, 15, 64, 3, 54, 28, 57, 67, 9, 75, 32, 65, 96, 17, 18, 29, 10, 14, 42, 6, 46, 26, 40, 59, 63, 78, 68, 8, 86, 51, 25, 72, 38, 97, 19, 81, 27, 41, 52, 22], [26, 32, 34, 79, 42, 45, 4, 75, 22, 73, 64, 98, 49, 19, 5, 24, 6, 55, 63, 25, 40, 77, 54, 12, 9, 44, 83, 71, 0, 90, 97, 96, 81, 80, 3, 31, 56, 92, 17, 86, 72, 28, 36, 78, 62, 30, 7, 46, 87, 20, 82, 50, 35, 61, 41, 94, 68, 11, 1, 10, 74, 67, 85, 43, 57, 15, 95, 84, 65, 53, 69, 52, 76, 88, 2, 14, 37, 58, 93, 16, 59, 51, 18, 99, 39, 47, 89, 8, 13, 91, 38, 33, 70, 48, 23, 29, 27, 66, 60, 21], [28, 53, 30, 85, 0, 95, 70, 47, 40, 51, 94, 68, 99, 15, 5, 57, 1, 16, 80, 93, 91, 52, 2, 32, 48, 77, 41, 75, 22, 39, 50, 81, 79, 73, 97, 76, 60, 4, 59, 25, 78, 38, 46, 58, 90, 84, 56, 6, 83, 62, 42, 10, 64, 31, 36, 61, 65, 63, 18, 8, 9, 96, 55, 26, 89, 67, 3, 98, 35, 21, 13, 12, 88, 71, 37, 29, 87, 49, 24, 86, 92, 20, 44, 74, 69, 17, 82, 54, 27, 7, 23, 66, 11, 19, 34, 45, 14, 72, 43, 33], [32, 44, 86, 79, 38, 61, 25, 8, 5, 85, 78, 48, 33, 87, 84, 35, 64, 41, 60, 21, 96, 75, 6, 69, 39, 94, 3, 92, 37, 77, 15, 13, 29, 59, 76, 91, 65, 56, 73, 83, 27, 62, 89, 50, 18, 98, 81, 17, 71, 28, 82, 11, 30, 43, 34, 20, 70, 22, 46, 63, 52, 68, 90, 53, 36, 10, 74, 58, 40, 88, 9, 2, 42, 26, 24, 4, 95, 57, 31, 66, 0, 14, 49, 16, 99, 19, 51, 23, 47, 12, 93, 1, 7, 80, 45, 97, 55, 67, 72, 54], [58, 35, 42, 38, 63, 36, 68, 30, 81, 4, 87, 80, 32, 69, 37, 67, 1, 86, 61, 94, 27, 11, 84, 26, 59, 73, 53, 66, 72, 71, 39, 33, 99, 8, 43, 88, 17, 22, 89, 5, 46, 93, 98, 48, 55, 83, 34, 3, 0, 16, 12, 20, 78, 9, 2, 76, 54, 51, 25, 24, 62, 57, 92, 10, 50, 28, 79, 23, 52, 95, 44, 60, 74, 90, 19, 77, 21, 31, 96, 49, 64, 6, 29, 85, 18, 13, 82, 47, 56, 45, 15, 7, 97, 75, 40, 41, 65, 14, 70, 91], [81, 82, 66, 72, 83, 4, 20, 94, 53, 48, 77, 41, 67, 64, 9, 24, 36, 55, 14, 1, 78, 84, 49, 0, 44, 58, 70, 25, 28, 73, 8, 68, 88, 54, 86, 87, 23, 52, 27, 5, 97, 37, 62, 50, 3, 89, 92, 47, 30, 10, 29, 80, 22, 26, 11, 13, 69, 60, 38, 90, 85, 57, 12, 75, 46, 39, 74, 33, 42, 93, 98, 91, 59, 99, 18, 6, 17, 16, 32, 40, 63, 7, 76, 15, 43, 71, 51, 35, 2, 65, 34, 96, 19, 56, 79, 21, 95, 45, 61, 31], [25, 88, 7, 57, 98, 63, 86, 13, 69, 84, 56, 20, 68, 90, 35, 6, 43, 93, 95, 3, 75, 4, 9, 28, 31, 66, 21, 44, 30, 76, 11, 22, 49, 2, 77, 40, 85, 19, 82, 16, 97, 92, 39, 96, 18, 32, 42, 94, 70, 71, 54, 79, 67, 78, 37, 12, 99, 53, 61, 41, 87, 17, 1, 14, 52, 10, 47, 58, 27, 46, 36, 55, 26, 15, 33, 50, 72, 51, 89, 23, 74, 59, 64, 8, 83, 65, 80, 29, 38, 0, 60, 24, 45, 81, 48, 91, 73, 5, 34, 62], [73, 85, 37, 11, 80, 46, 16, 47, 88, 65, 94, 64, 12, 38, 98, 70, 95, 48, 92, 18, 56, 75, 58, 7, 81, 15, 74, 13, 5, 44, 27, 32, 76, 90, 33, 55, 26, 96, 77, 24, 0, 89, 8, 4, 28, 39, 71, 3, 10, 41, 91, 53, 31, 68, 36, 17, 69, 60, 34, 54, 93, 82, 21, 51, 87, 59, 61, 6, 1, 23, 30, 66, 43, 25, 35, 42, 49, 78, 62, 14, 19, 20, 29, 22, 52, 83, 63, 45, 2, 99, 50, 79, 72, 40, 84, 97, 86, 57, 67, 9], [48, 94, 17, 55, 59, 24, 72, 75, 38, 85, 34, 98, 95, 36, 49, 63, 57, 54, 29, 6, 52, 47, 73, 1, 82, 9, 66, 83, 31, 61, 78, 60, 97, 14, 87, 15, 90, 70, 53, 10, 27, 8, 3, 64, 51, 50, 68, 26, 22, 19, 42, 96, 67, 7, 25, 39, 92, 30, 58, 93, 21, 74, 41, 18, 65, 44, 88, 32, 71, 69, 12, 77, 13, 11, 99, 79, 37, 89, 81, 35, 86, 56, 45, 76, 46, 80, 62, 43, 16, 84, 40, 5, 33, 91, 4, 20, 0, 23, 28, 2], [61, 45, 79, 13, 59, 52, 6, 77, 3, 31, 70, 80, 26, 33, 36, 4, 27, 32, 24, 74, 29, 94, 16, 12, 76, 7, 88, 57, 78, 42, 97, 96, 43, 83, 92, 21, 51, 47, 49, 58, 90, 41, 93, 98, 35, 63, 86, 37, 5, 30, 28, 72, 25, 22, 60, 19, 39, 34, 68, 50, 8, 64, 46, 99, 84, 87, 69, 56, 53, 55, 44, 54, 89, 65, 85, 0, 71, 15, 17, 66, 81, 82, 91, 95, 62, 48, 38, 75, 40, 14, 9, 10, 73, 67, 18, 11, 23, 2, 20, 1]], [[95, 90, 61, 38, 18, 7, 83, 39, 79, 14, 48, 21, 81, 44, 78, 50, 56, 91, 12, 86, 99, 98, 43, 63, 73, 87, 42, 72, 15, 68, 97, 23, 88, 69, 2, 51, 19, 58, 59, 22, 20, 29, 82, 11, 75, 70, 9, 71, 27, 30, 47, 89, 92, 60, 46, 76, 93, 54, 1, 96, 94, 57, 40, 62, 41, 3, 28, 64, 37, 74, 67, 16, 65, 53, 5, 36, 24, 45, 32, 33, 10, 85, 26, 4, 84, 77, 35, 13, 6, 8, 17, 80, 25, 55, 52, 66, 49, 34, 0, 31], [18, 14, 70, 43, 74, 45, 94, 36, 40, 6, 31, 46, 15, 47, 13, 19, 72, 61, 99, 21, 17, 92, 88, 78, 73, 90, 0, 96, 20, 28, 25, 51, 50, 77, 29, 16, 54, 12, 58, 38, 71, 23, 42, 83, 65, 60, 10, 33, 22, 76, 95, 32, 57, 5, 59, 67, 68, 3, 91, 85, 26, 62, 41, 1, 53, 82, 34, 24, 87, 27, 89, 75, 56, 30, 81, 7, 8, 4, 64, 66, 9, 63, 35, 52, 80, 93, 69, 84, 55, 86, 48, 98, 79, 97, 49, 44, 39, 11, 37, 2], [76, 16, 73, 29, 34, 14, 36, 90, 58, 70, 46, 2, 91, 59, 63, 32, 84, 40, 78, 38, 19, 37, 0, 31, 8, 44, 94, 39, 10, 66, 42, 1, 21, 88, 82, 97, 33, 4, 99, 74, 89, 62, 25, 87, 77, 43, 50, 95, 64, 23, 47, 93, 65, 27, 12, 71, 9, 72, 60, 18, 7, 22, 79, 24, 96, 45, 49, 98, 57, 11, 5, 86, 3, 80, 26, 51, 17, 85, 54, 67, 48, 35, 53, 41, 28, 13, 20, 92, 83, 69, 6, 68, 75, 52, 61, 30, 81, 56, 15, 55], [0, 62, 25, 61, 56, 87, 54, 27, 75, 49, 18, 69, 17, 71, 40, 6, 90, 80, 23, 26, 68, 24, 10, 21, 47, 88, 36, 55, 15, 22, 48, 12, 83, 99, 46, 67, 59, 29, 58, 73, 78, 97, 19, 33, 51, 98, 65, 91, 16, 4, 63, 41, 3, 70, 30, 8, 89, 34, 72, 60, 9, 95, 50, 2, 66, 53, 44, 85, 28, 5, 92, 43, 64, 96, 74, 77, 45, 52, 14, 42, 1, 32, 20, 76, 86, 82, 94, 7, 39, 13, 31, 11, 84, 93, 35, 37, 38, 57, 79, 81], [78, 8, 59, 25, 69, 15, 63, 3, 57, 5, 50, 96, 41, 66, 80, 81, 7, 45, 60, 74, 79, 32, 27, 58, 56, 82, 11, 47, 17, 85, 53, 40, 95, 84, 76, 92, 18, 71, 64, 51, 67, 91, 22, 34, 65, 31, 73, 93, 68, 75, 77, 37, 43, 12, 20, 99, 2, 1, 19, 35, 44, 55, 90, 9, 0, 6, 33, 89, 24, 14, 97, 10, 48, 61, 23, 54, 98, 86, 88, 94, 46, 70, 28, 36, 16, 30, 4, 39, 26, 38, 87, 52, 83, 49, 62, 42, 72, 29, 13, 21], [20, 88, 35, 5, 85, 98, 11, 78, 62, 83, 79, 80, 40, 14, 91, 8, 7, 69, 71, 61, 49, 38, 64, 82, 0, 47, 84, 95, 2, 50, 77, 41, 97, 36, 33, 81, 46, 21, 73, 48, 31, 92, 54, 89, 87, 60, 90, 10, 76, 45, 99, 52, 3, 44, 39, 43, 18, 16, 63, 12, 28, 70, 86, 6, 4, 24, 59, 30, 96, 65, 22, 56, 74, 23, 32, 75, 53, 93, 15, 67, 66, 17, 29, 25, 42, 37, 57, 9, 72, 68, 26, 34, 27, 51, 19, 58, 55, 94, 13, 1], [72, 53, 79, 61, 30, 33, 25, 75, 8, 55, 14, 6, 22, 93, 18, 77, 4, 74, 44, 36, 82, 94, 2, 5, 62, 54, 28, 3, 63, 97, 65, 7, 84, 73, 39, 92, 67, 91, 24, 45, 15, 81, 19, 78, 80, 64, 34, 43, 32, 87, 52, 95, 89, 37, 10, 23, 20, 68, 42, 47, 59, 58, 49, 71, 40, 85, 13, 31, 12, 57, 96, 90, 56, 41, 48, 9, 99, 35, 98, 26, 1, 46, 11, 69, 27, 83, 60, 50, 21, 70, 0, 88, 29, 86, 76, 16, 66, 38, 51, 17], [3, 68, 86, 94, 81, 90, 85, 32, 65, 52, 50, 42, 80, 78, 26, 93, 57, 58, 69, 82, 92, 27, 11, 67, 95, 41, 21, 88, 35, 17, 19, 15, 22, 62, 40, 76, 63, 59, 37, 55, 75, 9, 24, 89, 56, 53, 23, 60, 25, 6, 1, 71, 16, 7, 10, 44, 8, 12, 87, 64, 54, 72, 20, 33, 70, 79, 14, 97, 4, 99, 45, 39, 2, 77, 98, 74, 49, 30, 13, 61, 66, 73, 47, 43, 96, 83, 18, 91, 28, 48, 38, 34, 31, 36, 29, 0, 84, 46, 5, 51], [71, 84, 25, 70, 77, 56, 61, 47, 72, 27, 54, 89, 9, 46, 95, 59, 42, 98, 63, 69, 48, 16, 97, 14, 66, 83, 87, 68, 17, 2, 15, 79, 31, 1, 57, 12, 33, 36, 0, 40, 21, 50, 76, 41, 10, 13, 44, 5, 53, 4, 38, 35, 55, 96, 81, 91, 90, 64, 34, 51, 6, 28, 32, 39, 75, 18, 93, 24, 78, 7, 52, 43, 49, 37, 74, 8, 58, 65, 92, 67, 85, 20, 94, 88, 80, 86, 19, 60, 3, 11, 30, 45, 29, 22, 26, 73, 99, 23, 62, 82], [67, 91, 46, 33, 76, 3, 96, 23, 9, 68, 49, 63, 1, 92, 58, 62, 69, 77, 70, 75, 71, 94, 51, 55, 50, 52, 0, 88, 18, 16, 73, 6, 12, 87, 93, 79, 84, 57, 48, 41, 20, 47, 15, 42, 54, 81, 7, 30, 34, 56, 29, 8, 98, 5, 45, 64, 83, 74, 22, 82, 80, 95, 2, 72, 44, 31, 86, 78, 13, 10, 28, 89, 60, 35, 61, 19, 14, 85, 4, 43, 11, 40, 26, 99, 39, 32, 90, 17, 24, 37, 36, 21, 25, 53, 97, 59, 27, 38, 65, 66]], [[40, 77, 66, 65, 97, 96, 58, 64, 69, 30, 0, 3, 17, 33, 51, 23, 59, 10, 7, 20, 29, 49, 71, 13, 46, 4, 79, 92, 47, 18, 72, 57, 73, 80, 56, 28, 78, 67, 9, 87, 43, 31, 22, 62, 75, 99, 19, 63, 35, 93, 12, 98, 25, 26, 37, 89, 86, 15, 55, 50, 91, 38, 42, 81, 2, 94, 70, 68, 45, 88, 76, 74, 11, 24, 41, 60, 85, 21, 44, 32, 82, 61, 52, 83, 53, 36, 48, 1, 95, 27, 14, 84, 54, 6, 39, 34, 90, 5, 16, 8], [44, 69, 53, 28, 18, 11, 23, 65, 96, 25, 93, 42, 72, 58, 95, 56, 32, 21, 78, 77, 51, 34, 47, 7, 66, 13, 88, 67, 92, 98, 10, 50, 90, 45, 49, 9, 99, 94, 22, 24, 5, 85, 33, 3, 73, 35, 52, 63, 2, 76, 87, 43, 81, 83, 55, 61, 70, 75, 16, 14, 8, 71, 57, 40, 86, 39, 80, 79, 26, 48, 59, 4, 82, 0, 36, 12, 54, 38, 64, 17, 91, 27, 62, 84, 37, 74, 68, 1, 6, 19, 29, 46, 60, 30, 89, 15, 20, 97, 41, 31], [53, 22, 34, 16, 72, 71, 14, 94, 12, 59, 39, 6, 38, 68, 21, 93, 32, 46, 69, 55, 10, 8, 75, 60, 9, 13, 99, 90, 63, 49, 28, 92, 41, 7, 54, 83, 27, 91, 47, 43, 31, 74, 42, 40, 18, 81, 76, 84, 78, 52, 1, 26, 51, 2, 58, 11, 65, 67, 15, 23, 0, 79, 96, 4, 29, 62, 89, 66, 50, 98, 56, 61, 30, 88, 35, 25, 77, 70, 3, 44, 95, 80, 19, 64, 57, 37, 82, 85, 73, 48, 5, 86, 24, 36, 33, 97, 20, 45, 17, 87], [95, 36, 70, 82, 23, 55, 13, 51, 83, 38, 40, 18, 84, 74, 56, 85, 58, 14, 19, 69, 34, 59, 97, 89, 52, 77, 9, 91, 68, 16, 27, 88, 6, 73, 43, 5, 10, 66, 4, 61, 44, 46, 72, 50, 96, 21, 33, 15, 32, 0, 63, 92, 24, 39, 29, 49, 30, 64, 12, 26, 67, 53, 37, 2, 47, 65, 3, 20, 75, 78, 99, 87, 98, 1, 81, 90, 62, 54, 22, 35, 45, 25, 86, 48, 17, 60, 94, 8, 42, 31, 76, 28, 11, 57, 93, 41, 7, 71, 80, 79], [60, 24, 69, 92, 15, 36, 11, 98, 93, 27, 51, 35, 89, 74, 87, 4, 81, 94, 23, 84, 56, 3, 42, 18, 75, 73, 46, 86, 55, 99, 0, 88, 1, 26, 76, 70, 65, 67, 20, 13, 7, 45, 77, 17, 9, 78, 54, 48, 32, 40, 47, 31, 2, 6, 90, 10, 8, 50, 52, 38, 91, 14, 53, 12, 85, 44, 21, 80, 68, 33, 30, 57, 61, 63, 79, 41, 29, 39, 58, 5, 62, 96, 28, 71, 82, 34, 25, 43, 22, 95, 72, 37, 64, 16, 97, 59, 66, 83, 49, 19], [80, 0, 40, 36, 68, 18, 67, 14, 20, 21, 10, 17, 43, 3, 98, 81, 94, 55, 1, 39, 72, 51, 41, 66, 58, 2, 61, 78, 15, 99, 57, 52, 25, 87, 12, 65, 74, 64, 34, 37, 44, 30, 88, 79, 33, 27, 56, 35, 73, 42, 29, 54, 24, 5, 53, 16, 31, 4, 19, 84, 59, 50, 26, 63, 48, 28, 60, 45, 92, 82, 49, 77, 97, 76, 22, 86, 47, 62, 83, 70, 93, 38, 11, 13, 89, 75, 85, 69, 9, 46, 96, 90, 6, 91, 8, 7, 32, 71, 95, 23], [32, 14, 35, 84, 89, 11, 52, 34, 79, 65, 2, 88, 49, 29, 31, 94, 1, 74, 97, 51, 99, 37, 10, 47, 57, 81, 73, 76, 63, 58, 0, 38, 39, 27, 33, 8, 20, 21, 46, 66, 92, 36, 6, 30, 53, 17, 48, 64, 55, 28, 85, 50, 54, 12, 80, 41, 77, 69, 93, 9, 91, 13, 42, 75, 68, 86, 19, 3, 16, 78, 87, 45, 43, 56, 59, 70, 40, 24, 83, 98, 62, 5, 96, 4, 67, 60, 26, 23, 72, 95, 44, 82, 90, 25, 7, 18, 15, 22, 71, 61], [78, 53, 89, 93, 7, 84, 81, 95, 64, 50, 58, 35, 59, 63, 20, 76, 80, 8, 23, 28, 79, 52, 55, 48, 66, 17, 60, 65, 25, 29, 30, 9, 73, 39, 69, 3, 98, 22, 15, 87, 4, 37, 43, 5, 11, 83, 91, 40, 51, 33, 12, 92, 6, 67, 41, 94, 45, 88, 56, 36, 0, 68, 19, 54, 70, 26, 72, 77, 32, 34, 97, 71, 99, 75, 61, 31, 86, 82, 46, 2, 44, 96, 49, 74, 10, 62, 24, 16, 1, 38, 27, 14, 18, 85, 13, 57, 90, 21, 42, 47], [26, 30, 60, 78, 75, 48, 73, 52, 51, 57, 63, 90, 27, 36, 83, 81, 41, 44, 82, 37, 10, 64, 91, 4, 59, 95, 21, 24, 77, 56, 43, 38, 62, 55, 92, 0, 94, 20, 86, 66, 35, 80, 53, 25, 17, 18, 49, 76, 23, 89, 13, 15, 68, 8, 22, 46, 1, 42, 3, 34, 98, 88, 69, 31, 50, 65, 84, 32, 47, 61, 9, 19, 99, 85, 11, 79, 70, 2, 74, 14, 87, 7, 72, 5, 12, 58, 67, 39, 16, 71, 54, 6, 45, 93, 96, 28, 97, 29, 33, 40], [77, 66, 20, 30, 42, 23, 0, 49, 7, 64, 54, 27, 96, 97, 39, 84, 2, 51, 71, 17, 4, 92, 94, 95, 67, 69, 73, 75, 86, 37, 74, 50, 11, 79, 29, 15, 56, 43, 22, 83, 81, 61, 14, 3, 36, 44, 58, 10, 62, 19, 72, 80, 65, 24, 18, 5, 40, 90, 33, 9, 47, 76, 8, 59, 35, 91, 99, 13, 70, 88, 55, 16, 31, 28, 85, 45, 60, 25, 87, 82, 93, 12, 34, 68, 63, 26, 46, 48, 21, 52, 1, 78, 98, 38, 6, 32, 89, 53, 41, 57]], [[77, 99, 47, 64, 26, 63, 50, 81, 23, 45, 49, 36, 43, 56, 39, 12, 86, 62, 2, 98, 60, 94, 75, 9, 20, 74, 48, 28, 4, 84, 61, 31, 54, 15, 40, 7, 87, 38, 80, 6, 37, 46, 1, 55, 88, 73, 95, 33, 92, 18, 25, 66, 57, 27, 42, 35, 91, 51, 13, 90, 41, 83, 68, 53, 19, 3, 72, 89, 65, 70, 71, 8, 97, 59, 96, 52, 79, 22, 14, 69, 32, 93, 58, 29, 21, 76, 34, 5, 17, 67, 11, 78, 16, 0, 44, 30, 10, 24, 85, 82], [58, 62, 7, 39, 34, 69, 67, 73, 37, 59, 71, 66, 46, 57, 44, 51, 26, 85, 11, 28, 54, 47, 82, 21, 83, 76, 94, 16, 90, 95, 75, 55, 6, 22, 72, 74, 50, 40, 10, 19, 8, 53, 33, 98, 45, 87, 91, 13, 35, 70, 14, 38, 84, 99, 56, 30, 12, 89, 25, 97, 63, 65, 81, 92, 18, 29, 80, 61, 93, 43, 49, 52, 23, 31, 32, 4, 48, 3, 0, 78, 96, 64, 41, 88, 24, 5, 9, 15, 77, 86, 68, 1, 17, 79, 60, 36, 42, 2, 20, 27], [58, 62, 7, 39, 34, 69, 67, 73, 37, 59, 71, 66, 46, 57, 44, 51, 26, 85, 11, 28, 54, 47, 82, 21, 83, 76, 94, 16, 90, 95, 75, 55, 6, 22, 72, 74, 50, 40, 10, 19, 8, 53, 33, 98, 45, 87, 91, 13, 35, 70, 14, 38, 84, 99, 56, 30, 12, 89, 25, 97, 63, 65, 81, 92, 18, 29, 80, 61, 93, 43, 49, 52, 23, 31, 32, 4, 48, 3, 0, 78, 96, 64, 41, 88, 24, 5, 9, 15, 77, 86, 68, 1, 17, 79, 60, 36, 42, 2, 20, 27], [91, 43, 77, 69, 16, 96, 47, 34, 49, 15, 73, 84, 85, 22, 88, 95, 2, 80, 57, 33, 32, 41, 25, 14, 58, 9, 20, 65, 48, 97, 79, 89, 66, 63, 46, 83, 19, 92, 55, 18, 38, 0, 21, 50, 45, 62, 29, 26, 52, 28, 8, 6, 75, 86, 44, 81, 36, 90, 70, 30, 71, 39, 82, 87, 76, 1, 23, 5, 60, 98, 67, 53, 93, 72, 42, 74, 51, 4, 31, 59, 61, 7, 24, 56, 37, 54, 3, 11, 27, 40, 10, 64, 94, 35, 78, 68, 99, 17, 12, 13], [73, 70, 39, 9, 77, 61, 80, 10, 13, 92, 38, 4, 48, 57, 25, 72, 49, 51, 99, 97, 85, 36, 22, 15, 8, 34, 33, 76, 26, 45, 83, 59, 28, 96, 90, 47, 68, 88, 44, 6, 98, 12, 24, 46, 2, 54, 5, 58, 30, 63, 1, 18, 93, 67, 7, 50, 31, 16, 40, 56, 23, 86, 11, 52, 55, 75, 71, 27, 37, 87, 84, 65, 82, 29, 0, 14, 41, 35, 64, 21, 3, 95, 17, 60, 81, 74, 19, 91, 94, 32, 69, 53, 42, 89, 79, 43, 66, 20, 78, 62], [23, 78, 67, 41, 9, 77, 59, 72, 25, 82, 65, 89, 28, 37, 54, 70, 98, 33, 31, 44, 6, 17, 26, 73, 21, 36, 4, 2, 79, 95, 81, 50, 18, 34, 61, 0, 93, 24, 8, 66, 55, 62, 56, 30, 84, 58, 7, 88, 85, 64, 97, 39, 49, 3, 20, 42, 80, 96, 13, 63, 43, 60, 47, 90, 51, 14, 53, 1, 86, 57, 12, 19, 10, 45, 38, 68, 35, 87, 75, 5, 69, 27, 32, 91, 11, 99, 46, 29, 92, 22, 76, 15, 16, 48, 71, 74, 52, 94, 83, 40], [87, 89, 35, 98, 44, 21, 29, 83, 0, 77, 34, 60, 85, 64, 28, 58, 39, 36, 95, 22, 67, 30, 86, 57, 5, 81, 84, 26, 53, 62, 13, 90, 2, 88, 4, 46, 97, 73, 79, 43, 59, 72, 54, 32, 82, 10, 55, 38, 47, 12, 51, 1, 76, 48, 7, 14, 23, 20, 31, 18, 17, 15, 37, 42, 49, 68, 25, 93, 91, 40, 92, 50, 52, 70, 33, 80, 19, 96, 61, 75, 71, 99, 74, 9, 41, 66, 63, 8, 6, 24, 65, 56, 45, 69, 27, 16, 3, 78, 94, 11], [99, 6, 38, 11, 34, 28, 86, 57, 55, 78, 25, 95, 13, 63, 91, 14, 83, 1, 45, 17, 93, 76, 46, 79, 27, 85, 96, 58, 59, 44, 87, 65, 97, 22, 0, 51, 49, 52, 47, 67, 24, 88, 62, 50, 72, 3, 31, 82, 68, 42, 81, 23, 32, 98, 73, 60, 37, 54, 41, 80, 66, 18, 92, 4, 5, 94, 77, 39, 69, 16, 35, 7, 40, 30, 61, 26, 56, 64, 9, 71, 19, 21, 75, 84, 43, 53, 33, 29, 74, 36, 90, 2, 20, 15, 10, 48, 89, 70, 8, 12], [4, 28, 8, 72, 74, 31, 66, 0, 27, 54, 61, 23, 51, 73, 96, 32, 98, 41, 88, 95, 36, 22, 13, 38, 70, 84, 12, 7, 10, 60, 68, 33, 11, 35, 79, 42, 16, 62, 57, 24, 44, 94, 25, 48, 86, 97, 87, 49, 92, 71, 21, 1, 81, 5, 17, 85, 6, 75, 80, 34, 20, 30, 90, 69, 18, 89, 93, 56, 91, 40, 77, 52, 53, 14, 65, 45, 76, 2, 9, 29, 3, 26, 59, 55, 83, 46, 67, 47, 39, 50, 58, 63, 99, 15, 37, 43, 82, 64, 78, 19], [11, 94, 1, 93, 59, 91, 89, 51, 61, 81, 13, 29, 27, 58, 26, 3, 53, 69, 73, 21, 39, 12, 5, 18, 98, 74, 9, 96, 28, 65, 23, 4, 41, 72, 88, 34, 83, 54, 7, 15, 38, 84, 90, 52, 77, 48, 64, 60, 20, 79, 19, 66, 97, 30, 87, 45, 40, 36, 14, 86, 32, 33, 57, 16, 43, 42, 50, 10, 44, 76, 37, 6, 56, 31, 68, 99, 2, 17, 22, 35, 92, 85, 46, 75, 71, 67, 95, 78, 8, 63, 82, 25, 80, 24, 47, 49, 0, 70, 62, 55]], [[93, 99, 51, 49, 71, 64, 35, 42, 88, 17, 67, 92, 4, 12, 68, 13, 47, 7, 56, 14, 19, 53, 80, 85, 23, 5, 39, 6, 26, 89, 27, 54, 63, 73, 70, 33, 36, 3, 86, 58, 18, 2, 25, 21, 10, 34, 81, 94, 75, 98, 37, 46, 9, 95, 60, 74, 87, 78, 20, 24, 57, 0, 30, 83, 72, 61, 11, 32, 43, 82, 65, 69, 59, 62, 38, 76, 22, 16, 15, 45, 48, 79, 50, 90, 40, 1, 29, 77, 91, 31, 84, 96, 8, 52, 97, 41, 28, 44, 55, 66], [64, 71, 19, 27, 43, 95, 77, 16, 35, 81, 74, 29, 6, 86, 18, 37, 99, 46, 15, 87, 28, 63, 1, 65, 3, 79, 50, 12, 78, 84, 8, 88, 98, 69, 42, 0, 56, 32, 92, 83, 30, 59, 80, 9, 20, 89, 47, 23, 33, 34, 82, 24, 97, 60, 22, 90, 51, 76, 10, 94, 21, 91, 70, 49, 66, 14, 75, 2, 7, 13, 40, 93, 48, 36, 53, 72, 67, 62, 85, 17, 57, 58, 5, 25, 41, 31, 44, 73, 61, 26, 38, 54, 96, 39, 4, 68, 11, 52, 45, 55], [49, 88, 62, 73, 34, 15, 95, 68, 98, 5, 61, 35, 23, 45, 78, 64, 97, 70, 96, 65, 74, 16, 94, 37, 80, 56, 48, 28, 59, 1, 75, 4, 71, 47, 83, 93, 69, 21, 60, 38, 39, 19, 40, 82, 55, 7, 52, 18, 43, 54, 2, 77, 66, 90, 44, 32, 89, 3, 24, 6, 99, 17, 86, 29, 30, 22, 50, 81, 41, 42, 0, 9, 53, 58, 57, 25, 20, 12, 26, 51, 92, 87, 36, 31, 85, 63, 14, 8, 91, 11, 79, 27, 76, 84, 67, 33, 72, 13, 10, 46], [45, 15, 69, 88, 51, 28, 34, 80, 30, 42, 38, 90, 47, 17, 84, 49, 21, 55, 46, 96, 37, 97, 72, 85, 94, 29, 10, 66, 76, 82, 18, 86, 87, 25, 43, 92, 19, 89, 2, 93, 98, 40, 48, 53, 75, 99, 11, 62, 12, 60, 3, 24, 4, 6, 63, 81, 41, 20, 68, 9, 57, 52, 0, 44, 14, 16, 91, 27, 79, 73, 59, 61, 78, 7, 67, 1, 70, 83, 74, 64, 26, 95, 54, 65, 33, 39, 5, 50, 36, 35, 13, 23, 58, 71, 32, 77, 31, 22, 56, 8], [41, 43, 66, 69, 22, 23, 71, 2, 33, 38, 86, 51, 55, 59, 82, 96, 45, 97, 73, 34, 70, 21, 8, 58, 84, 90, 24, 25, 32, 78, 17, 27, 47, 68, 37, 72, 63, 77, 87, 89, 50, 16, 83, 54, 12, 56, 64, 62, 39, 92, 91, 53, 29, 76, 52, 94, 42, 81, 20, 98, 40, 79, 44, 10, 31, 0, 57, 19, 75, 67, 93, 6, 7, 11, 74, 26, 85, 5, 1, 49, 4, 61, 95, 3, 36, 9, 14, 13, 15, 48, 80, 46, 30, 65, 99, 18, 60, 88, 35, 28], [5, 56, 10, 81, 42, 35, 12, 94, 34, 13, 8, 0, 49, 17, 7, 69, 30, 1, 65, 14, 39, 2, 58, 76, 54, 31, 50, 46, 11, 27, 22, 61, 74, 64, 91, 18, 48, 63, 71, 57, 95, 87, 47, 67, 77, 53, 88, 23, 3, 83, 29, 86, 43, 60, 70, 78, 21, 99, 36, 66, 20, 62, 85, 4, 80, 98, 79, 82, 97, 15, 96, 52, 51, 6, 40, 93, 28, 41, 72, 45, 68, 16, 32, 75, 84, 89, 26, 55, 9, 59, 73, 24, 25, 33, 37, 19, 90, 44, 38, 92], [62, 28, 97, 69, 65, 46, 27, 96, 29, 73, 89, 42, 16, 36, 44, 63, 80, 60, 11, 54, 87, 92, 75, 81, 57, 26, 70, 49, 76, 10, 95, 84, 56, 22, 20, 9, 21, 61, 1, 47, 34, 19, 66, 0, 33, 91, 45, 3, 2, 90, 88, 43, 51, 12, 7, 18, 24, 85, 86, 8, 78, 38, 55, 30, 6, 35, 15, 93, 14, 99, 98, 82, 52, 74, 4, 50, 79, 37, 77, 17, 41, 71, 58, 53, 68, 39, 67, 25, 5, 83, 94, 13, 48, 32, 23, 59, 31, 64, 72, 40], [93, 20, 18, 22, 94, 27, 39, 59, 4, 11, 6, 75, 98, 62, 63, 81, 44, 53, 25, 95, 74, 57, 76, 5, 70, 60, 99, 12, 56, 85, 41, 67, 46, 19, 28, 1, 23, 80, 32, 68, 31, 51, 82, 55, 78, 77, 58, 69, 38, 87, 91, 79, 96, 52, 47, 73, 83, 89, 65, 3, 92, 14, 43, 66, 61, 37, 84, 54, 33, 88, 35, 71, 42, 90, 72, 50, 7, 40, 0, 24, 9, 29, 49, 45, 15, 21, 86, 64, 16, 36, 34, 17, 26, 10, 2, 13, 8, 97, 30, 48], [33, 3, 7, 64, 74, 23, 42, 25, 68, 85, 5, 8, 83, 17, 56, 79, 70, 73, 15, 6, 36, 18, 94, 97, 72, 22, 11, 96, 40, 58, 66, 49, 62, 86, 78, 67, 26, 98, 90, 48, 14, 2, 82, 91, 9, 76, 69, 44, 50, 47, 53, 71, 92, 12, 59, 37, 19, 60, 39, 13, 77, 16, 55, 41, 84, 31, 65, 27, 99, 51, 4, 45, 80, 46, 57, 21, 28, 81, 54, 29, 61, 88, 52, 43, 75, 20, 1, 10, 0, 35, 30, 32, 95, 38, 63, 87, 89, 24, 34, 93], [37, 25, 50, 66, 86, 23, 76, 27, 83, 97, 89, 35, 32, 41, 33, 87, 14, 59, 48, 61, 52, 3, 73, 67, 24, 56, 93, 22, 7, 70, 77, 28, 91, 30, 68, 29, 60, 8, 94, 13, 43, 17, 88, 57, 81, 34, 15, 95, 79, 96, 72, 84, 55, 46, 58, 10, 12, 38, 11, 99, 53, 42, 65, 44, 31, 21, 82, 6, 92, 26, 51, 5, 39, 63, 40, 9, 49, 18, 78, 80, 71, 74, 90, 2, 54, 47, 85, 75, 69, 45, 0, 16, 19, 1, 64, 98, 4, 62, 36, 20]]];\nconst sbtable2 = [[3, 5, 8, 6, 0, 9, 7, 1, 2, 4], [1, 3, 9, 4, 2, 0, 8, 7, 5, 6], [0, 5, 1, 7, 9, 8, 6, 2, 3, 4], [6, 4, 7, 8, 3, 0, 9, 5, 2, 1], [2, 3, 8, 1, 9, 7, 6, 0, 4, 5], [3, 4, 1, 7, 2, 8, 6, 0, 9, 5], [6, 1, 8, 3, 0, 4, 2, 7, 5, 9], [9, 3, 7, 5, 2, 4, 0, 6, 1, 8], [6, 1, 5, 3, 0, 8, 7, 4, 2, 9], [9, 7, 4, 5, 1, 2, 3, 0, 8, 6]];\n\nconst ibtable = [[[11, 38, 3, 63, 36, 39, 79, 19, 87, 68, 76, 51, 20, 56, 77, 61, 52, 73, 74, 94, 45, 31, 99, 28, 29, 90, 81, 96, 65, 75, 13, 32, 70, 21, 55, 33, 9, 15, 92, 14, 82, 97, 78, 37, 49, 0, 80, 57, 58, 7, 1, 89, 98, 53, 64, 5, 6, 66, 43, 83, 10, 50, 47, 84, 62, 71, 4, 67, 86, 42, 35, 34, 91, 12, 17, 69, 44, 48, 85, 30, 16, 95, 54, 23, 46, 18, 88, 59, 40, 60, 41, 25, 27, 22, 2, 24, 72, 93, 26, 8], [28, 58, 74, 34, 6, 14, 16, 46, 87, 24, 59, 57, 23, 88, 75, 65, 79, 38, 82, 13, 49, 99, 8, 94, 15, 19, 0, 96, 41, 95, 45, 35, 1, 91, 2, 52, 42, 76, 90, 84, 20, 54, 4, 63, 25, 5, 47, 85, 93, 12, 51, 81, 71, 69, 22, 17, 36, 64, 77, 80, 98, 53, 44, 18, 10, 68, 97, 61, 56, 70, 92, 27, 40, 9, 60, 7, 72, 21, 43, 3, 33, 32, 50, 26, 67, 62, 39, 48, 73, 86, 29, 89, 37, 78, 55, 66, 31, 30, 11, 83], [4, 16, 22, 66, 37, 14, 47, 89, 59, 60, 51, 92, 71, 70, 96, 13, 17, 85, 58, 93, 81, 69, 28, 90, 78, 39, 63, 88, 0, 75, 2, 53, 23, 99, 94, 68, 54, 74, 41, 29, 8, 26, 50, 98, 82, 95, 42, 7, 24, 77, 30, 9, 21, 1, 87, 62, 46, 15, 43, 38, 36, 55, 49, 57, 52, 56, 91, 65, 11, 84, 6, 73, 97, 33, 83, 27, 35, 25, 40, 32, 18, 31, 86, 48, 45, 3, 79, 76, 72, 64, 44, 20, 80, 19, 10, 5, 61, 34, 67, 12], [80, 91, 71, 26, 75, 8, 22, 92, 7, 70, 65, 51, 89, 31, 81, 30, 83, 47, 44, 85, 55, 19, 57, 87, 74, 6, 73, 40, 49, 32, 52, 78, 0, 12, 54, 15, 64, 28, 4, 24, 68, 17, 72, 53, 1, 94, 58, 88, 11, 82, 43, 86, 60, 63, 99, 96, 37, 77, 67, 33, 18, 5, 41, 59, 16, 36, 79, 97, 61, 23, 56, 48, 98, 38, 66, 21, 34, 29, 10, 3, 93, 46, 50, 39, 14, 9, 2, 13, 69, 42, 62, 35, 27, 90, 25, 76, 20, 95, 45, 84], [48, 16, 54, 47, 9, 39, 81, 91, 33, 53, 63, 21, 50, 85, 97, 90, 49, 36, 84, 74, 51, 76, 37, 67, 59, 58, 23, 20, 65, 82, 7, 77, 12, 31, 46, 1, 5, 14, 3, 30, 94, 95, 2, 34, 70, 89, 40, 87, 43, 79, 64, 57, 68, 26, 56, 44, 88, 61, 0, 24, 71, 18, 60, 4, 80, 96, 27, 15, 6, 13, 98, 29, 28, 25, 72, 93, 55, 75, 52, 66, 11, 8, 86, 45, 22, 83, 17, 10, 35, 38, 73, 99, 62, 41, 19, 69, 78, 92, 42, 32], [23, 19, 88, 44, 5, 39, 75, 81, 30, 14, 49, 54, 62, 55, 18, 83, 77, 76, 74, 92, 6, 95, 52, 36, 15, 27, 53, 38, 28, 50, 48, 99, 78, 67, 90, 87, 16, 41, 58, 65, 79, 11, 68, 84, 24, 97, 64, 47, 9, 22, 43, 86, 37, 8, 33, 17, 93, 61, 25, 72, 57, 98, 42, 80, 13, 89, 2, 12, 31, 56, 26, 85, 3, 29, 66, 63, 82, 10, 20, 94, 51, 0, 1, 4, 21, 60, 34, 35, 32, 45, 59, 71, 46, 69, 7, 96, 91, 40, 70, 73], [89, 62, 33, 19, 21, 97, 15, 2, 83, 22, 65, 30, 55, 7, 63, 73, 39, 61, 44, 37, 11, 26, 31, 79, 91, 0, 72, 68, 23, 87, 28, 24, 45, 74, 98, 14, 70, 54, 88, 42, 35, 59, 46, 16, 27, 92, 69, 66, 94, 32, 75, 77, 64, 57, 50, 71, 10, 3, 67, 81, 90, 58, 99, 5, 82, 85, 25, 52, 12, 8, 48, 49, 76, 96, 80, 20, 29, 34, 53, 51, 86, 93, 38, 84, 9, 36, 6, 60, 1, 78, 13, 95, 41, 17, 47, 18, 43, 40, 4, 56], [40, 68, 88, 47, 43, 28, 67, 23, 42, 99, 48, 3, 12, 27, 79, 25, 6, 55, 19, 80, 81, 62, 83, 69, 39, 73, 36, 30, 44, 82, 70, 52, 31, 34, 58, 74, 54, 2, 13, 45, 93, 49, 75, 72, 29, 87, 5, 7, 17, 76, 90, 63, 84, 51, 59, 35, 20, 97, 22, 65, 57, 66, 78, 86, 11, 9, 71, 98, 53, 56, 15, 46, 92, 0, 26, 21, 32, 38, 77, 91, 4, 24, 61, 85, 94, 1, 96, 64, 8, 41, 33, 50, 18, 60, 10, 16, 37, 95, 14, 89], [96, 23, 99, 42, 94, 91, 19, 53, 41, 25, 39, 73, 70, 72, 33, 35, 88, 2, 63, 49, 95, 60, 48, 97, 5, 54, 47, 40, 98, 18, 57, 28, 67, 92, 10, 79, 13, 76, 8, 55, 90, 62, 50, 87, 65, 82, 84, 21, 0, 14, 45, 44, 20, 38, 17, 3, 81, 16, 58, 4, 31, 29, 86, 15, 43, 64, 26, 52, 46, 69, 37, 68, 6, 22, 61, 7, 83, 71, 30, 75, 85, 78, 24, 27, 89, 9, 80, 34, 66, 77, 36, 93, 56, 59, 1, 12, 51, 32, 11, 74], [75, 99, 97, 8, 15, 48, 6, 25, 60, 90, 91, 95, 23, 3, 89, 77, 22, 78, 94, 55, 98, 35, 53, 96, 18, 52, 12, 16, 50, 20, 49, 9, 17, 13, 57, 44, 14, 47, 86, 56, 88, 41, 29, 32, 70, 1, 62, 37, 85, 38, 59, 36, 5, 68, 71, 69, 67, 27, 39, 4, 54, 0, 84, 45, 61, 73, 79, 93, 58, 66, 10, 76, 51, 92, 19, 87, 24, 7, 28, 2, 11, 80, 81, 33, 64, 74, 46, 65, 26, 72, 40, 82, 34, 42, 21, 83, 31, 30, 43, 63]], [[98, 58, 34, 65, 83, 74, 88, 5, 89, 46, 80, 43, 18, 87, 9, 28, 71, 90, 4, 36, 40, 11, 39, 31, 76, 92, 82, 48, 66, 41, 49, 99, 78, 79, 97, 86, 75, 68, 3, 7, 62, 64, 26, 22, 13, 77, 54, 50, 10, 96, 15, 35, 94, 73, 57, 93, 16, 61, 37, 38, 53, 2, 63, 23, 67, 72, 95, 70, 29, 33, 45, 47, 27, 24, 69, 44, 55, 85, 14, 8, 91, 12, 42, 6, 84, 81, 19, 25, 32, 51, 1, 17, 52, 56, 60, 0, 59, 30, 21, 20], [26, 63, 99, 57, 77, 53, 9, 75, 76, 80, 46, 97, 37, 14, 1, 12, 35, 20, 0, 15, 28, 19, 48, 41, 67, 30, 60, 69, 29, 34, 73, 10, 51, 47, 66, 82, 7, 98, 39, 96, 8, 62, 42, 3, 95, 5, 11, 13, 90, 94, 32, 31, 83, 64, 36, 88, 72, 52, 38, 54, 45, 17, 61, 81, 78, 44, 79, 55, 56, 86, 2, 40, 16, 24, 4, 71, 49, 33, 23, 92, 84, 74, 65, 43, 87, 59, 89, 68, 22, 70, 25, 58, 21, 85, 6, 50, 27, 93, 91, 18], [22, 31, 11, 72, 37, 70, 90, 60, 24, 56, 28, 69, 54, 85, 5, 98, 1, 76, 59, 20, 86, 32, 61, 49, 63, 42, 74, 53, 84, 3, 95, 23, 15, 36, 4, 81, 6, 21, 19, 27, 17, 83, 30, 45, 25, 65, 10, 50, 80, 66, 46, 75, 93, 82, 78, 99, 97, 68, 8, 13, 58, 94, 41, 14, 48, 52, 29, 79, 91, 89, 9, 55, 57, 2, 39, 92, 0, 44, 18, 62, 73, 96, 34, 88, 16, 77, 71, 43, 33, 40, 7, 12, 87, 51, 26, 47, 64, 35, 67, 38], [0, 80, 63, 52, 49, 69, 15, 87, 55, 60, 22, 91, 31, 89, 78, 28, 48, 12, 10, 42, 82, 23, 29, 18, 21, 2, 19, 7, 68, 37, 54, 90, 81, 43, 57, 94, 26, 95, 96, 88, 14, 51, 79, 71, 66, 76, 34, 24, 30, 9, 62, 44, 77, 65, 6, 27, 4, 97, 38, 36, 59, 3, 1, 50, 72, 46, 64, 35, 20, 11, 53, 13, 58, 39, 74, 8, 83, 75, 40, 98, 17, 99, 85, 32, 92, 67, 84, 5, 25, 56, 16, 47, 70, 93, 86, 61, 73, 41, 45, 33], [64, 57, 56, 7, 86, 9, 65, 16, 1, 63, 71, 26, 53, 98, 69, 5, 84, 28, 36, 58, 54, 99, 42, 74, 68, 3, 88, 22, 82, 97, 85, 45, 21, 66, 43, 59, 83, 51, 89, 87, 31, 12, 95, 52, 60, 17, 80, 27, 72, 93, 10, 39, 91, 30, 75, 61, 24, 8, 23, 2, 18, 73, 94, 6, 38, 44, 13, 40, 48, 4, 81, 37, 96, 46, 19, 49, 34, 50, 0, 20, 14, 15, 25, 92, 33, 29, 77, 90, 78, 67, 62, 41, 35, 47, 79, 32, 11, 70, 76, 55], [24, 99, 28, 52, 64, 3, 63, 16, 15, 87, 47, 6, 59, 98, 13, 78, 57, 81, 56, 94, 0, 37, 70, 73, 65, 83, 90, 92, 60, 82, 67, 40, 74, 34, 91, 2, 33, 85, 21, 54, 12, 31, 84, 55, 53, 49, 36, 25, 39, 20, 29, 93, 51, 76, 42, 96, 71, 86, 95, 66, 45, 19, 8, 58, 22, 69, 80, 79, 89, 17, 61, 18, 88, 38, 72, 75, 48, 30, 7, 10, 11, 35, 23, 9, 26, 4, 62, 44, 1, 43, 46, 14, 41, 77, 97, 27, 68, 32, 5, 50], [90, 80, 22, 27, 16, 23, 11, 31, 8, 75, 54, 82, 68, 66, 10, 40, 95, 99, 14, 42, 56, 88, 12, 55, 38, 6, 79, 84, 26, 92, 4, 67, 48, 5, 46, 77, 19, 53, 97, 34, 64, 73, 58, 47, 18, 39, 81, 59, 74, 62, 87, 98, 50, 1, 25, 9, 72, 69, 61, 60, 86, 3, 24, 28, 45, 30, 96, 36, 57, 83, 89, 63, 0, 33, 17, 7, 94, 15, 43, 2, 44, 41, 20, 85, 32, 65, 93, 49, 91, 52, 71, 37, 35, 13, 21, 51, 70, 29, 78, 76], [95, 50, 72, 0, 68, 98, 49, 53, 56, 41, 54, 22, 57, 78, 66, 31, 52, 29, 86, 30, 62, 26, 32, 46, 42, 48, 14, 21, 88, 94, 77, 92, 7, 63, 91, 28, 93, 38, 90, 71, 34, 25, 11, 83, 55, 70, 97, 82, 89, 76, 10, 99, 9, 45, 60, 39, 44, 16, 17, 37, 47, 79, 33, 36, 59, 8, 80, 23, 1, 18, 64, 51, 61, 81, 75, 40, 35, 73, 13, 65, 12, 4, 19, 85, 96, 6, 2, 58, 27, 43, 5, 87, 20, 15, 3, 24, 84, 67, 74, 69], [38, 33, 29, 88, 49, 47, 60, 69, 75, 12, 44, 89, 35, 45, 23, 30, 21, 28, 65, 86, 81, 40, 93, 97, 67, 2, 94, 9, 61, 92, 90, 32, 62, 36, 58, 51, 37, 73, 50, 63, 39, 43, 16, 71, 46, 91, 13, 7, 20, 72, 41, 59, 70, 48, 10, 52, 5, 34, 76, 15, 87, 6, 98, 18, 57, 77, 24, 79, 27, 19, 3, 0, 8, 95, 74, 64, 42, 4, 68, 31, 84, 54, 99, 25, 1, 80, 85, 26, 83, 11, 56, 55, 78, 66, 82, 14, 53, 22, 17, 96], [26, 12, 62, 5, 78, 53, 31, 46, 51, 8, 69, 80, 32, 68, 76, 42, 29, 87, 28, 75, 40, 91, 58, 7, 88, 92, 82, 96, 70, 50, 47, 65, 85, 3, 48, 73, 90, 89, 97, 84, 81, 39, 43, 79, 64, 54, 2, 41, 38, 10, 24, 22, 25, 93, 44, 23, 49, 37, 14, 95, 72, 74, 15, 11, 55, 98, 99, 0, 9, 16, 18, 20, 63, 30, 57, 19, 4, 17, 67, 35, 60, 45, 59, 56, 36, 77, 66, 33, 27, 71, 86, 1, 13, 34, 21, 61, 6, 94, 52, 83]], [[10, 87, 64, 11, 25, 97, 93, 18, 99, 38, 17, 72, 50, 23, 90, 57, 98, 12, 29, 46, 19, 77, 42, 15, 73, 52, 53, 89, 35, 20, 9, 41, 79, 13, 95, 48, 85, 54, 61, 94, 0, 74, 62, 40, 78, 68, 24, 28, 86, 21, 59, 14, 82, 84, 92, 58, 34, 31, 6, 16, 75, 81, 43, 47, 7, 3, 2, 37, 67, 8, 66, 22, 30, 32, 71, 44, 70, 1, 36, 26, 33, 63, 80, 83, 91, 76, 56, 39, 69, 55, 96, 60, 27, 49, 65, 88, 5, 4, 51, 45], [73, 87, 48, 43, 71, 40, 88, 23, 60, 35, 30, 5, 75, 25, 59, 95, 58, 79, 4, 89, 96, 17, 38, 6, 39, 9, 68, 81, 3, 90, 93, 99, 16, 42, 21, 45, 74, 84, 77, 65, 63, 98, 11, 51, 0, 33, 91, 22, 69, 34, 31, 20, 46, 2, 76, 54, 15, 62, 13, 70, 92, 55, 82, 47, 78, 7, 24, 27, 86, 1, 56, 61, 12, 44, 85, 57, 49, 19, 18, 67, 66, 52, 72, 53, 83, 41, 64, 50, 26, 94, 32, 80, 28, 10, 37, 14, 8, 97, 29, 36], [60, 50, 53, 78, 63, 90, 11, 33, 21, 24, 20, 55, 8, 25, 6, 58, 3, 98, 44, 82, 96, 14, 1, 59, 92, 75, 51, 36, 30, 64, 72, 40, 16, 94, 2, 74, 93, 85, 12, 10, 43, 32, 42, 39, 79, 97, 17, 38, 89, 29, 68, 52, 49, 0, 34, 19, 70, 84, 54, 9, 23, 71, 65, 28, 83, 56, 67, 57, 13, 18, 77, 5, 4, 88, 41, 22, 46, 76, 48, 61, 81, 45, 86, 35, 47, 87, 91, 99, 73, 66, 27, 37, 31, 15, 7, 80, 62, 95, 69, 26], [49, 73, 63, 66, 38, 35, 32, 96, 87, 26, 36, 92, 58, 6, 17, 47, 29, 84, 11, 18, 67, 45, 78, 4, 52, 81, 59, 30, 91, 54, 56, 89, 48, 46, 20, 79, 1, 62, 9, 53, 10, 95, 88, 34, 40, 80, 41, 64, 83, 55, 43, 7, 24, 61, 77, 5, 14, 93, 16, 21, 85, 39, 76, 50, 57, 65, 37, 60, 28, 19, 2, 97, 42, 33, 13, 68, 90, 25, 69, 99, 98, 74, 3, 8, 12, 15, 82, 71, 31, 23, 75, 27, 51, 94, 86, 0, 44, 22, 72, 70], [30, 32, 52, 21, 15, 79, 53, 40, 56, 44, 55, 6, 63, 39, 61, 4, 93, 43, 23, 99, 38, 66, 88, 18, 1, 86, 33, 9, 82, 76, 70, 51, 48, 69, 85, 11, 5, 91, 59, 77, 49, 75, 22, 87, 65, 41, 26, 50, 47, 98, 57, 10, 58, 62, 46, 28, 20, 71, 78, 95, 0, 72, 80, 73, 92, 36, 96, 37, 68, 2, 35, 83, 90, 25, 13, 24, 34, 42, 45, 74, 67, 16, 84, 97, 19, 64, 27, 14, 31, 12, 54, 60, 3, 8, 17, 89, 81, 94, 7, 29], [1, 18, 25, 13, 57, 53, 92, 95, 94, 88, 10, 82, 34, 83, 7, 28, 55, 11, 5, 58, 8, 9, 74, 99, 52, 32, 62, 45, 65, 50, 41, 56, 96, 44, 38, 47, 3, 39, 81, 19, 2, 22, 49, 12, 40, 67, 89, 76, 64, 70, 61, 21, 31, 54, 51, 17, 46, 30, 24, 60, 66, 26, 77, 63, 37, 35, 23, 6, 4, 87, 79, 97, 20, 48, 36, 85, 73, 71, 27, 43, 0, 15, 69, 78, 59, 86, 75, 33, 42, 84, 91, 93, 68, 80, 16, 98, 90, 72, 14, 29], [30, 16, 10, 67, 83, 81, 42, 94, 35, 59, 22, 5, 53, 61, 1, 96, 68, 45, 95, 66, 36, 37, 97, 87, 77, 93, 86, 33, 49, 13, 43, 14, 0, 34, 7, 2, 41, 21, 31, 32, 76, 55, 62, 72, 90, 71, 38, 23, 46, 12, 51, 19, 6, 44, 52, 48, 73, 24, 29, 74, 85, 99, 80, 28, 47, 9, 39, 84, 64, 57, 75, 98, 88, 26, 17, 63, 27, 56, 69, 8, 54, 25, 91, 78, 3, 50, 65, 70, 11, 4, 92, 60, 40, 58, 15, 89, 82, 18, 79, 20], [60, 88, 79, 35, 40, 43, 52, 4, 17, 31, 84, 44, 50, 94, 91, 38, 87, 25, 92, 62, 14, 97, 37, 18, 86, 28, 65, 90, 19, 29, 30, 75, 68, 49, 69, 11, 59, 41, 89, 33, 47, 54, 98, 42, 80, 56, 78, 99, 23, 82, 9, 48, 21, 1, 63, 22, 58, 95, 10, 12, 26, 74, 85, 13, 8, 27, 24, 53, 61, 34, 64, 71, 66, 32, 83, 73, 15, 67, 0, 20, 16, 6, 77, 45, 5, 93, 76, 39, 57, 2, 96, 46, 51, 3, 55, 7, 81, 70, 36, 72], [35, 56, 77, 58, 23, 83, 91, 81, 53, 70, 20, 74, 84, 50, 79, 51, 88, 44, 45, 71, 37, 26, 54, 48, 27, 43, 0, 12, 95, 97, 1, 63, 67, 98, 59, 40, 13, 19, 31, 87, 99, 16, 57, 30, 17, 92, 55, 68, 5, 46, 64, 8, 7, 42, 90, 33, 29, 9, 85, 24, 2, 69, 32, 10, 21, 65, 39, 86, 52, 62, 76, 89, 82, 6, 78, 4, 47, 28, 3, 75, 41, 15, 18, 14, 66, 73, 38, 80, 61, 49, 11, 22, 34, 93, 36, 25, 94, 96, 60, 72], [6, 90, 16, 43, 20, 55, 94, 8, 62, 59, 47, 32, 81, 67, 42, 35, 71, 19, 54, 49, 2, 88, 38, 5, 53, 77, 85, 11, 73, 34, 3, 72, 95, 58, 82, 64, 44, 29, 93, 14, 56, 98, 4, 37, 45, 75, 86, 60, 87, 7, 31, 17, 89, 97, 10, 70, 36, 99, 46, 63, 76, 41, 48, 84, 9, 52, 1, 24, 83, 25, 68, 18, 50, 26, 30, 27, 61, 0, 91, 33, 51, 40, 79, 39, 15, 74, 28, 78, 69, 96, 57, 65, 21, 80, 22, 23, 12, 13, 92, 66]], [[93, 42, 18, 65, 28, 87, 39, 35, 71, 23, 96, 90, 15, 58, 78, 33, 92, 88, 49, 64, 24, 84, 77, 8, 97, 50, 4, 53, 27, 83, 95, 31, 80, 47, 86, 55, 11, 40, 37, 14, 34, 60, 54, 12, 94, 9, 41, 2, 26, 10, 6, 57, 75, 63, 32, 43, 13, 52, 82, 73, 20, 30, 17, 5, 3, 68, 51, 89, 62, 79, 69, 70, 66, 45, 25, 22, 85, 0, 91, 76, 38, 7, 99, 61, 29, 98, 16, 36, 44, 67, 59, 56, 48, 81, 21, 46, 74, 72, 19, 1], [78, 91, 97, 77, 75, 85, 32, 2, 40, 86, 38, 18, 56, 47, 50, 87, 27, 92, 64, 39, 98, 23, 33, 72, 84, 58, 16, 99, 19, 65, 55, 73, 74, 42, 4, 48, 95, 8, 51, 3, 37, 82, 96, 69, 14, 44, 12, 21, 76, 70, 36, 15, 71, 41, 20, 31, 54, 13, 0, 9, 94, 67, 1, 60, 81, 61, 11, 6, 90, 5, 49, 10, 34, 7, 35, 30, 25, 88, 79, 93, 66, 62, 22, 24, 52, 17, 89, 45, 83, 57, 28, 46, 63, 68, 26, 29, 80, 59, 43, 53], [78, 91, 97, 77, 75, 85, 32, 2, 40, 86, 38, 18, 56, 47, 50, 87, 27, 92, 64, 39, 98, 23, 33, 72, 84, 58, 16, 99, 19, 65, 55, 73, 74, 42, 4, 48, 95, 8, 51, 3, 37, 82, 96, 69, 14, 44, 12, 21, 76, 70, 36, 15, 71, 41, 20, 31, 54, 13, 0, 9, 94, 67, 1, 60, 81, 61, 11, 6, 90, 5, 49, 10, 34, 7, 35, 30, 25, 88, 79, 93, 66, 62, 22, 24, 52, 17, 89, 45, 83, 57, 28, 46, 63, 68, 26, 29, 80, 59, 43, 53], [41, 65, 16, 86, 77, 67, 51, 81, 50, 25, 90, 87, 98, 99, 23, 9, 4, 97, 39, 36, 26, 42, 13, 66, 82, 22, 47, 88, 49, 46, 59, 78, 20, 19, 7, 93, 56, 84, 40, 61, 89, 21, 74, 1, 54, 44, 34, 6, 28, 8, 43, 76, 48, 71, 85, 38, 83, 18, 24, 79, 68, 80, 45, 33, 91, 27, 32, 70, 95, 3, 58, 60, 73, 10, 75, 52, 64, 2, 94, 30, 17, 55, 62, 35, 11, 12, 53, 63, 14, 31, 57, 0, 37, 72, 92, 15, 5, 29, 69, 96], [74, 50, 44, 80, 11, 46, 39, 54, 24, 3, 7, 62, 41, 8, 75, 23, 57, 82, 51, 86, 97, 79, 22, 60, 42, 14, 28, 67, 32, 73, 48, 56, 89, 26, 25, 77, 21, 68, 10, 2, 58, 76, 92, 95, 38, 29, 43, 35, 12, 16, 55, 17, 63, 91, 45, 64, 59, 13, 47, 31, 83, 5, 99, 49, 78, 71, 96, 53, 36, 90, 1, 66, 15, 0, 85, 65, 27, 4, 98, 94, 6, 84, 72, 30, 70, 20, 61, 69, 37, 93, 34, 87, 9, 52, 88, 81, 33, 19, 40, 18], [35, 67, 27, 53, 26, 79, 20, 46, 38, 4, 72, 84, 70, 58, 65, 91, 92, 21, 32, 71, 54, 24, 89, 0, 37, 8, 22, 81, 12, 87, 43, 18, 82, 17, 33, 76, 25, 13, 74, 51, 99, 3, 55, 60, 19, 73, 86, 62, 93, 52, 31, 64, 96, 66, 14, 40, 42, 69, 45, 6, 61, 34, 41, 59, 49, 10, 39, 2, 75, 80, 15, 94, 7, 23, 95, 78, 90, 5, 1, 28, 56, 30, 9, 98, 44, 48, 68, 77, 47, 11, 63, 83, 88, 36, 97, 29, 57, 50, 16, 85], [8, 51, 32, 96, 34, 24, 88, 54, 87, 83, 45, 99, 49, 30, 55, 61, 95, 60, 59, 76, 57, 5, 19, 56, 89, 66, 27, 94, 14, 6, 21, 58, 43, 74, 10, 2, 17, 62, 47, 16, 69, 84, 63, 39, 4, 92, 35, 48, 53, 64, 71, 50, 72, 28, 42, 46, 91, 23, 15, 40, 11, 78, 29, 86, 13, 90, 85, 20, 65, 93, 73, 80, 41, 37, 82, 79, 52, 9, 97, 38, 75, 25, 44, 7, 26, 12, 22, 0, 33, 1, 31, 68, 70, 67, 98, 18, 77, 36, 3, 81], [34, 17, 91, 45, 63, 64, 1, 71, 98, 78, 94, 3, 99, 12, 15, 93, 69, 19, 61, 80, 92, 81, 33, 51, 40, 10, 75, 24, 5, 87, 73, 46, 52, 86, 4, 70, 89, 56, 2, 67, 72, 58, 49, 84, 29, 18, 22, 38, 95, 36, 43, 35, 37, 85, 57, 8, 76, 7, 27, 28, 55, 74, 42, 13, 77, 31, 60, 39, 48, 68, 97, 79, 44, 54, 88, 82, 21, 66, 9, 23, 59, 50, 47, 16, 83, 25, 6, 30, 41, 96, 90, 14, 62, 20, 65, 11, 26, 32, 53, 0], [7, 51, 77, 80, 0, 53, 56, 27, 2, 78, 28, 32, 26, 22, 73, 93, 36, 54, 64, 99, 60, 50, 21, 11, 39, 42, 81, 8, 1, 79, 61, 5, 15, 31, 59, 33, 20, 94, 23, 88, 69, 17, 35, 95, 40, 75, 85, 87, 43, 47, 89, 12, 71, 72, 9, 83, 67, 38, 90, 82, 29, 10, 37, 91, 97, 74, 6, 86, 30, 63, 24, 49, 3, 13, 4, 57, 76, 70, 98, 34, 58, 52, 96, 84, 25, 55, 44, 46, 18, 65, 62, 68, 48, 66, 41, 19, 14, 45, 16, 92], [96, 2, 76, 15, 31, 22, 71, 38, 88, 26, 67, 0, 21, 10, 58, 39, 63, 77, 23, 50, 48, 19, 78, 30, 93, 91, 14, 12, 28, 11, 53, 73, 60, 61, 35, 79, 57, 70, 40, 20, 56, 32, 65, 64, 68, 55, 82, 94, 45, 95, 66, 7, 43, 16, 37, 99, 72, 62, 13, 4, 47, 8, 98, 89, 46, 29, 51, 85, 74, 17, 97, 84, 33, 18, 25, 83, 69, 44, 87, 49, 92, 9, 90, 36, 41, 81, 59, 54, 34, 6, 42, 5, 80, 3, 1, 86, 27, 52, 24, 75]], [[61, 85, 41, 37, 12, 25, 27, 17, 92, 52, 44, 66, 13, 15, 19, 78, 77, 9, 40, 20, 58, 43, 76, 24, 59, 42, 28, 30, 96, 86, 62, 89, 67, 35, 45, 6, 36, 50, 74, 26, 84, 95, 7, 68, 97, 79, 51, 16, 80, 3, 82, 2, 93, 21, 31, 98, 18, 60, 39, 72, 54, 65, 73, 32, 5, 70, 99, 10, 14, 71, 34, 4, 64, 33, 55, 48, 75, 87, 57, 81, 22, 46, 69, 63, 90, 23, 38, 56, 8, 29, 83, 88, 11, 0, 47, 53, 91, 94, 49, 1], [35, 22, 67, 24, 94, 82, 12, 68, 30, 43, 58, 96, 27, 69, 65, 18, 7, 79, 14, 2, 44, 60, 54, 47, 51, 83, 89, 3, 20, 11, 40, 85, 37, 48, 49, 8, 73, 15, 90, 93, 70, 84, 34, 4, 86, 98, 17, 46, 72, 63, 26, 56, 97, 74, 91, 99, 36, 80, 81, 41, 53, 88, 77, 21, 0, 23, 64, 76, 95, 33, 62, 1, 75, 87, 10, 66, 57, 6, 28, 25, 42, 9, 50, 39, 29, 78, 13, 19, 31, 45, 55, 61, 38, 71, 59, 5, 92, 52, 32, 16], [70, 29, 50, 57, 31, 9, 59, 45, 87, 71, 98, 89, 77, 97, 86, 5, 21, 61, 47, 41, 76, 37, 65, 12, 58, 75, 78, 91, 27, 63, 64, 83, 55, 95, 4, 11, 82, 23, 39, 40, 42, 68, 69, 48, 54, 13, 99, 33, 26, 0, 66, 79, 46, 72, 49, 44, 25, 74, 73, 28, 38, 10, 2, 85, 15, 19, 52, 94, 7, 36, 17, 32, 96, 3, 20, 30, 92, 51, 14, 90, 24, 67, 43, 34, 93, 84, 62, 81, 1, 56, 53, 88, 80, 35, 22, 6, 18, 16, 8, 60], [62, 75, 38, 50, 52, 86, 53, 73, 99, 59, 26, 46, 48, 90, 64, 1, 65, 13, 30, 36, 57, 16, 97, 91, 51, 33, 80, 67, 5, 25, 8, 96, 94, 84, 6, 89, 88, 20, 10, 85, 41, 56, 9, 34, 63, 0, 18, 12, 42, 15, 87, 4, 61, 43, 82, 17, 98, 60, 92, 70, 49, 71, 47, 54, 79, 83, 27, 74, 58, 2, 76, 93, 22, 69, 78, 44, 28, 95, 72, 68, 7, 55, 29, 77, 14, 23, 31, 32, 3, 37, 11, 66, 35, 39, 24, 81, 19, 21, 40, 45], [65, 78, 7, 83, 80, 77, 71, 72, 22, 85, 63, 73, 44, 87, 86, 88, 41, 30, 95, 67, 58, 21, 4, 5, 26, 27, 75, 31, 99, 52, 92, 64, 28, 8, 19, 98, 84, 34, 9, 48, 60, 0, 56, 1, 62, 16, 91, 32, 89, 79, 40, 11, 54, 51, 43, 12, 45, 66, 23, 13, 96, 81, 47, 36, 46, 93, 2, 69, 33, 3, 20, 6, 35, 18, 74, 68, 53, 37, 29, 61, 90, 57, 14, 42, 24, 76, 10, 38, 97, 39, 25, 50, 49, 70, 55, 82, 15, 17, 59, 94], [11, 17, 21, 48, 63, 0, 73, 14, 10, 88, 2, 28, 6, 9, 19, 69, 81, 13, 35, 95, 60, 56, 30, 47, 91, 92, 86, 29, 76, 50, 16, 25, 82, 93, 8, 5, 58, 94, 98, 20, 74, 77, 4, 52, 97, 79, 27, 42, 36, 12, 26, 72, 71, 45, 24, 87, 1, 39, 22, 89, 53, 31, 61, 37, 33, 18, 59, 43, 80, 15, 54, 38, 78, 90, 32, 83, 23, 44, 55, 66, 64, 3, 67, 49, 84, 62, 51, 41, 46, 85, 96, 34, 99, 75, 7, 40, 70, 68, 65, 57], [43, 38, 48, 47, 74, 88, 64, 54, 59, 35, 29, 18, 53, 91, 68, 66, 12, 79, 55, 41, 34, 36, 33, 94, 56, 87, 25, 6, 1, 8, 63, 96, 93, 44, 40, 65, 13, 77, 61, 85, 99, 80, 11, 51, 14, 46, 5, 39, 92, 27, 75, 52, 72, 83, 19, 62, 32, 24, 82, 95, 17, 37, 0, 15, 97, 4, 42, 86, 84, 3, 26, 81, 98, 9, 73, 22, 28, 78, 60, 76, 16, 23, 71, 89, 31, 57, 58, 20, 50, 10, 49, 45, 21, 67, 90, 30, 7, 2, 70, 69], [78, 35, 94, 59, 8, 23, 10, 76, 96, 80, 93, 9, 27, 95, 61, 84, 88, 91, 2, 33, 1, 85, 3, 36, 79, 18, 92, 5, 34, 81, 98, 40, 38, 68, 90, 70, 89, 65, 48, 6, 77, 30, 72, 62, 16, 83, 32, 54, 99, 82, 75, 41, 53, 17, 67, 43, 28, 21, 46, 7, 25, 64, 13, 14, 87, 58, 63, 31, 39, 47, 24, 71, 74, 55, 20, 11, 22, 45, 44, 51, 37, 15, 42, 56, 66, 29, 86, 49, 69, 57, 73, 50, 60, 0, 4, 19, 52, 97, 12, 26], [88, 86, 41, 1, 70, 10, 19, 2, 11, 44, 87, 26, 53, 59, 40, 18, 61, 13, 21, 56, 85, 75, 25, 5, 97, 7, 36, 67, 76, 79, 90, 65, 91, 0, 98, 89, 20, 55, 93, 58, 28, 63, 6, 83, 47, 71, 73, 49, 39, 31, 48, 69, 82, 50, 78, 62, 14, 74, 29, 54, 57, 80, 32, 94, 3, 66, 30, 35, 8, 46, 16, 51, 24, 17, 4, 84, 45, 60, 34, 15, 72, 77, 42, 12, 64, 9, 33, 95, 81, 96, 38, 43, 52, 99, 22, 92, 27, 23, 37, 68], [90, 93, 83, 21, 96, 71, 67, 28, 37, 75, 55, 58, 56, 39, 16, 46, 91, 41, 77, 92, 99, 65, 27, 5, 24, 1, 69, 7, 31, 35, 33, 64, 12, 14, 45, 11, 98, 0, 57, 72, 74, 13, 61, 40, 63, 89, 53, 85, 18, 76, 2, 70, 20, 60, 84, 52, 25, 43, 54, 17, 36, 19, 97, 73, 94, 62, 3, 23, 34, 88, 29, 80, 50, 22, 81, 87, 6, 30, 78, 48, 79, 44, 66, 8, 51, 86, 4, 15, 42, 10, 82, 32, 68, 26, 38, 47, 49, 9, 95, 59]]];\nconst ibtable2 = [[4, 7, 8, 0, 9, 1, 3, 6, 2, 5], [5, 0, 4, 1, 3, 8, 9, 7, 6, 2], [0, 2, 7, 8, 9, 1, 6, 3, 5, 4], [5, 9, 8, 4, 1, 7, 0, 2, 3, 6], [7, 3, 0, 1, 8, 9, 6, 5, 2, 4], [7, 2, 4, 0, 1, 9, 6, 3, 5, 8], [4, 1, 6, 3, 5, 8, 0, 7, 2, 9], [6, 8, 4, 1, 5, 3, 7, 2, 9, 0], [4, 1, 8, 3, 7, 2, 0, 6, 5, 9], [7, 4, 5, 6, 2, 3, 9, 1, 8, 0]];\n\ntype DecodedAccessCode = { revision: number; serial: number };\n\nfunction crc16(data: BigInteger, bits: number, initial: number = 0xffff, poly: number = 0x8408): number {\n let v = bigInt(initial);\n let bigPoly = bigInt(poly);\n\n for (let i = 0; i < bits; i++) {\n v = v.shiftRight(1).xor(bigPoly.and(v.xor(data).and(bigInt.one).equals(bigInt.one) ? bigPoly : bigInt.zero));\n data = data.shiftRight(1);\n }\n\n return v.toJSNumber();\n}\n\nexport function decodeAccessCode(code: string): DecodedAccessCode | null {\n code = code.replace(/\\D/i, '');\n\n if (code.length !== 20) {\n return null;\n }\n\n let body = _.range(3, 15, 2).map(i => parseInt(code[i]) * 10 + parseInt(code[i + 1]));\n let crc = _.range(15, 20).map(i => parseInt(code[i]));\n\n let boxes = [(crc[3] + crc[2]) % 10, crc[2], crc[3], crc[4], (crc[4] + crc[0]) % 10, crc[1]];\n\n for (const [n, i] of body.entries()) {\n body[n] = ibtable[4][boxes[n]][i];\n }\n\n const rv = body[0] >> 4;\n\n boxes = [(crc[1] + crc[0]) % 10, crc[1], crc[2], crc[3], crc[4], (crc[4] + crc[1]) % 10]\n for (const [n, i] of body.entries()) {\n if (n == 0) {\n body[n] = (body[n] & 0xf0) | ibtable2[boxes[n]][body[n] & 0x0f];\n } else {\n body[n] = ibtable[rv][boxes[n]][i];\n }\n }\n\n const serial = body.map(i => i.toString().padStart(2, '0')).join('')\n\n if (crc16(bigInt(code.substring(0, 3) + serial, 16), 15 * 4) !== parseInt(code.substring(15, 20))) {\n throw new Error(`CRC16 mismatch.`);\n }\n\n return { revision: rv, serial: parseInt(serial) };\n}\n\nexport function encodeAccessCode(company: number, serial: number, rev: number = 0): string {\n if (company < 0 || company > 999) {\n throw new Error(`Invalid company code`);\n }\n\n if (serial < 0 || serial > 99999999999) {\n throw new Error(`Invalid serial number`);\n }\n\n if (rev < 0 || rev > sbtable.length) {\n throw new Error(`Invalid revision`);\n }\n\n const bodyStr = `${rev}${serial.toString().padStart(11, '0')}`;\n const crc_i = crc16(bigInt(company.toString().padStart(3, '0') + bodyStr, 16), 15 * 4);\n\n const crc = _.range(5).map(i => Math.floor(crc_i / (10 ** (4 - i))) % 10);\n const body = _.range(0, 12, 2).map(i => parseInt(bodyStr[i]) * 10 + parseInt(bodyStr[i + 1]));\n\n let boxes = [(crc[1] + crc[0]) % 10, crc[1], crc[2], crc[3], crc[4], (crc[4] + crc[1]) % 10];\n for (const [n, i] of body.entries()) {\n if (n == 0) {\n body[n] = (body[n] & 0xf0) | sbtable2[boxes[n]][body[n] & 0x0f];\n } else {\n body[n] = sbtable[rev][boxes[n]][i];\n }\n }\n\n boxes = [(crc[3] + crc[2]) % 10, crc[2], crc[3], crc[4], (crc[4] + crc[0]) % 10, crc[1]]\n for (const [n, i] of body.entries()) {\n body[n] = sbtable[4][boxes[n]][i];\n }\n\n return `${company.toString().padStart(3, '0')}${body.map(i => i.toString().padStart(2, '0')).join('')}${crc_i.toString().padStart(5, '0')}`;\n}\n","import {encodeAccessCode} from \"./card-encoding\";\n\nexport const CARD_ID_REGEX = /^(?:[0-9]{4} ?){5}$/i;\nexport const AMNET_COMPANY_ID = 597;\n\nexport function generateCardNumber(): string {\n // serial between 0 and 99999999999\n const serial = Math.floor(Math.random() * 100000000000);\n return encodeAccessCode(AMNET_COMPANY_ID, serial, 0);\n}\n\n/**\n * Validates the provided card id by known parameters\n * @param id The card id to validate\n */\nexport function validateCardId(id: string): boolean {\n return id[0] !== '3' && CARD_ID_REGEX.test(id);\n}\n","/**\n * Get the game name from the game identifier (4-letter code)\n * @param id\n */\nexport function getGameName(id: string): string | null {\n switch (id?.toUpperCase()) {\n case \"SDGT\":\n return \"Initial D The Arcade\";\n case \"SDHD\":\n case \"SDBT\":\n return \"CHUNITHM\";\n case \"SDDT\":\n return \"O.N.G.E.K.I.\";\n case \"SDEZ\":\n return \"maimai DX\";\n case \"SBZV\":\n return \"Project DIVA Future Tone\";\n \n default:\n return null;\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACGO,IAAM,oBAAoB;AAK1B,IAAM,wBAAwB;AA0CrC,eAAsB,cAAc,QAAgC,SAA0B,QAAuC;AACjI,MAAI,OAAO,aAAa,yBAAyB,OAAO,aAAa,mBAAmB;AACpF,UAAM,IAAI,MAAM,gCAAgC;AAAA,EACpD;AAEA,MAAI;AACA,UAAM,WAAW,MAAM,MAAM,GAAG,IAAI,IAAI,OAAO,aAAa,EAAE,MAAM,iBAAiB;AAAA,MACjF,QAAQ;AAAA,MACR,SAAS;AAAA,QACL,gBAAgB;AAAA,MACpB;AAAA,MACA,MAAM,KAAK,UAAU,OAAO;AAAA,MAC5B;AAAA,IACJ,CAAC;AAED,WAAO,SAAS;AAAA,EACpB,SAAQ;AACJ,WAAO;AAAA,EACX;AACJ;AAOA,eAAsB,gBAAgB,eAAuB,OAAkD;AAC3G,MAAI;AACA,UAAM,WAAW,MAAM,MAAM,GAAG,IAAI,IAAI,aAAa,EAAE,MAAM,eAAe;AAAA,MACxE,QAAQ;AAAA,IACZ,CAAC;AAED,QAAI,CAAC,SAAS,IAAI;AACd,aAAO;AAAA,IACX;AAEA,WAAO,iCACA,MAAM,SAAS,KAAK,IADpB;AAAA,MAEH;AAAA,IACJ;AAAA,EACJ,SAAQ;AACJ,WAAO;AAAA,EACX;AACJ;;;AC7FA,oBAAc;AACd,yBAAiC;AAEjC,IAAM,UAAU,CAAC,CAAC,CAAC,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,GAAG,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,EAAE,GAAG,CAAC,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,EAAE,GAAG,CAAC,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,EAAE,GAAG,CAAC,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,GAAG,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,EAAE,GAAG,CAAC,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,GAAG,IAAI,IAAI,IAAI,IAAI,GAAG,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,EAAE,GAAG,CAAC,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,EAAE,GAAG,CAAC,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,GAAG,IAAI,GAAG,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,EAAE,GAAG,CAAC,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,GAAG,GAAG,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,CAAC,GAAG,CAAC,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,GAAG,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,GAAG,IAAI,GAAG,IAAI,IAAI,CAAC,GAAG,CAAC,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,GAAG,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,EAAE,GAAG,CAAC,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,GAAG,GAAG,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,CAAC,GAAG,CAAC,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,EAAE,GAAG,CAAC,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,GAAG,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,EAAE,GAAG,CAAC,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,GAAG,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,EAAE,GAAG,CAAC,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,CAAC,GAAG,CAAC,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,GAAG,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,EAAE,GAAG,CAAC,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,GAAG,IAAI,IAAI,GAAG,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,GAAG,EAAE,GAAG,CAAC,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,EAAE,GAAG,CAAC,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,EAAE,CAAC,GAAG,CAAC,CAAC,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,EAAE,GAAG,CAAC,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,EAAE,GAAG,CAAC,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,GAAG,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,EAAE,GAAG,CAAC,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,GAAG,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,EAAE,GAAG,CAAC,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,GAAG,IAAI,GAAG,GAAG,IAAI,IAAI,IAAI,EAAE,GAAG,CAAC,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,EAAE,GAAG,CAAC,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,EAAE,GAAG,CAAC,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,GAAG,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,GAAG,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,EAAE,GAAG,CAAC,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,EAAE,CAAC,GAAG,CAAC,CAAC,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,EAAE,GAAG,CAAC,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,GAAG,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,GAAG,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,EAAE,GAAG,CAAC,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,GAAG,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,GAAG,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,EAAE,GAAG,CAAC,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,EAAE,GAAG,CAAC,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,GAAG,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,EAAE,GAAG,CAAC,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,EAAE,GAAG,CAAC,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,GAAG,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,EAAE,GAAG,CAAC,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,EAAE,GAAG,CAAC,GAAG,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,GAAG,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,GAAG,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,EAAE,GAAG,CAAC,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,EAAE,CAAC,GAAG,CAAC,CAAC,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,EAAE,GAAG,CAAC,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,EAAE,GAAG,CAAC,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,EAAE,GAAG,CAAC,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,GAAG,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,CAAC,GAAG,CAAC,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,GAAG,IAAI,IAAI,IAAI,IAAI,GAAG,GAAG,IAAI,GAAG,IAAI,IAAI,GAAG,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,EAAE,GAAG,CAAC,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,GAAG,IAAI,IAAI,GAAG,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,EAAE,GAAG,CAAC,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,GAAG,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,EAAE,GAAG,CAAC,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,GAAG,IAAI,IAAI,EAAE,GAAG,CAAC,IAAI,GAAG,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,EAAE,GAAG,CAAC,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,GAAG,IAAI,IAAI,GAAG,IAAI,IAAI,EAAE,CAAC,CAAC;AACzqmB,IAAM,WAAW,CAAC,CAAC,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC,GAAG,CAAC,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC,GAAG,CAAC,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC,GAAG,CAAC,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC,GAAG,CAAC,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC,GAAG,CAAC,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC,GAAG,CAAC,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC,GAAG,CAAC,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC,GAAG,CAAC,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC,GAAG,CAAC,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC,CAAC;AAEhV,IAAM,UAAU,CAAC,CAAC,CAAC,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,GAAG,GAAG,IAAI,IAAI,IAAI,IAAI,GAAG,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,CAAC,GAAG,CAAC,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,GAAG,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,EAAE,GAAG,CAAC,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,GAAG,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,EAAE,GAAG,CAAC,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,EAAE,GAAG,CAAC,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,GAAG,GAAG,IAAI,GAAG,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,EAAE,GAAG,CAAC,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,GAAG,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,EAAE,GAAG,CAAC,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,EAAE,GAAG,CAAC,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,EAAE,GAAG,CAAC,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,EAAE,GAAG,CAAC,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,EAAE,CAAC,GAAG,CAAC,CAAC,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,EAAE,GAAG,CAAC,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,GAAG,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,EAAE,GAAG,CAAC,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,GAAG,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,EAAE,GAAG,CAAC,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,GAAG,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,EAAE,GAAG,CAAC,IAAI,IAAI,IAAI,GAAG,IAAI,GAAG,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,GAAG,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,EAAE,GAAG,CAAC,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,GAAG,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,EAAE,GAAG,CAAC,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,EAAE,GAAG,CAAC,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,GAAG,GAAG,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,EAAE,GAAG,CAAC,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,GAAG,GAAG,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,EAAE,GAAG,CAAC,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,EAAE,CAAC,GAAG,CAAC,CAAC,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,GAAG,GAAG,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,GAAG,IAAI,EAAE,GAAG,CAAC,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,GAAG,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,EAAE,GAAG,CAAC,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,EAAE,GAAG,CAAC,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,EAAE,GAAG,CAAC,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,GAAG,IAAI,IAAI,IAAI,IAAI,GAAG,EAAE,GAAG,CAAC,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,GAAG,IAAI,GAAG,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,EAAE,GAAG,CAAC,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,GAAG,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,EAAE,GAAG,CAAC,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,GAAG,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,GAAG,IAAI,GAAG,IAAI,IAAI,IAAI,EAAE,GAAG,CAAC,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,GAAG,GAAG,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,GAAG,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,EAAE,GAAG,CAAC,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,EAAE,CAAC,GAAG,CAAC,CAAC,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,GAAG,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,CAAC,GAAG,CAAC,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,GAAG,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,GAAG,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,GAAG,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,EAAE,GAAG,CAAC,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,GAAG,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,GAAG,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,GAAG,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,EAAE,GAAG,CAAC,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,GAAG,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,EAAE,GAAG,CAAC,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,GAAG,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,EAAE,GAAG,CAAC,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,GAAG,GAAG,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,EAAE,GAAG,CAAC,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,GAAG,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,EAAE,GAAG,CAAC,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,CAAC,GAAG,CAAC,GAAG,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,GAAG,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,EAAE,GAAG,CAAC,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,GAAG,IAAI,IAAI,IAAI,IAAI,EAAE,CAAC,GAAG,CAAC,CAAC,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,CAAC,GAAG,CAAC,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,EAAE,GAAG,CAAC,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,GAAG,EAAE,GAAG,CAAC,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,GAAG,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,EAAE,GAAG,CAAC,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,GAAG,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,GAAG,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,EAAE,GAAG,CAAC,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,GAAG,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,EAAE,GAAG,CAAC,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,GAAG,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,GAAG,IAAI,EAAE,GAAG,CAAC,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,GAAG,IAAI,IAAI,IAAI,IAAI,EAAE,GAAG,CAAC,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,EAAE,GAAG,CAAC,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,EAAE,CAAC,CAAC;AACzqmB,IAAM,WAAW,CAAC,CAAC,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC,GAAG,CAAC,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC,GAAG,CAAC,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC,GAAG,CAAC,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC,GAAG,CAAC,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC,GAAG,CAAC,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC,GAAG,CAAC,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC,GAAG,CAAC,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC,GAAG,CAAC,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC,GAAG,CAAC,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC,CAAC;AAIhV,SAAS,MAAM,MAAkB,MAAc,UAAkB,OAAQ,OAAe,OAAgB;AACpG,MAAI,QAAI,mBAAAA,SAAO,OAAO;AACtB,MAAI,cAAU,mBAAAA,SAAO,IAAI;AAEzB,WAAS,IAAI,GAAG,IAAI,MAAM,KAAK;AAC3B,QAAI,EAAE,WAAW,CAAC,EAAE,IAAI,QAAQ,IAAI,EAAE,IAAI,IAAI,EAAE,IAAI,mBAAAA,QAAO,GAAG,EAAE,OAAO,mBAAAA,QAAO,GAAG,IAAI,UAAU,mBAAAA,QAAO,IAAI,CAAC;AAC3G,WAAO,KAAK,WAAW,CAAC;AAAA,EAC5B;AAEA,SAAO,EAAE,WAAW;AACxB;AAEO,SAAS,iBAAiB,MAAwC;AACrE,SAAO,KAAK,QAAQ,OAAO,EAAE;AAE7B,MAAI,KAAK,WAAW,IAAI;AACpB,WAAO;AAAA,EACX;AAEA,MAAI,OAAO,cAAAC,QAAE,MAAM,GAAG,IAAI,CAAC,EAAE,IAAI,OAAK,SAAS,KAAK,CAAC,CAAC,IAAI,KAAK,SAAS,KAAK,IAAI,CAAC,CAAC,CAAC;AACpF,MAAI,MAAM,cAAAA,QAAE,MAAM,IAAI,EAAE,EAAE,IAAI,OAAK,SAAS,KAAK,CAAC,CAAC,CAAC;AAEpD,MAAI,QAAQ,EAAE,IAAI,CAAC,IAAI,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,GAAG,IAAI,CAAC,GAAG,IAAI,CAAC,IAAI,IAAI,CAAC,IAAI,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,CAAC;AAE3F,aAAW,CAAC,GAAG,CAAC,KAAK,KAAK,QAAQ,GAAG;AACjC,SAAK,CAAC,IAAI,QAAQ,CAAC,EAAE,MAAM,CAAC,CAAC,EAAE,CAAC;AAAA,EACpC;AAEA,QAAM,KAAK,KAAK,CAAC,KAAK;AAEtB,UAAQ,EAAE,IAAI,CAAC,IAAI,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,GAAG,IAAI,CAAC,GAAG,IAAI,CAAC,GAAG,IAAI,CAAC,IAAI,IAAI,CAAC,IAAI,IAAI,CAAC,KAAK,EAAE;AACvF,aAAW,CAAC,GAAG,CAAC,KAAK,KAAK,QAAQ,GAAG;AACjC,QAAI,KAAK,GAAG;AACR,WAAK,CAAC,IAAK,KAAK,CAAC,IAAI,MAAQ,SAAS,MAAM,CAAC,CAAC,EAAE,KAAK,CAAC,IAAI,EAAI;AAAA,IAClE,OAAO;AACH,WAAK,CAAC,IAAI,QAAQ,EAAE,EAAE,MAAM,CAAC,CAAC,EAAE,CAAC;AAAA,IACrC;AAAA,EACJ;AAEA,QAAM,SAAS,KAAK,IAAI,OAAK,EAAE,SAAS,EAAE,SAAS,GAAG,GAAG,CAAC,EAAE,KAAK,EAAE;AAEnE,MAAI,UAAM,mBAAAD,SAAO,KAAK,UAAU,GAAG,CAAC,IAAI,QAAQ,EAAE,GAAG,KAAK,CAAC,MAAM,SAAS,KAAK,UAAU,IAAI,EAAE,CAAC,GAAG;AAC/F,UAAM,IAAI,MAAM,iBAAiB;AAAA,EACrC;AAEA,SAAO,EAAE,UAAU,IAAI,QAAQ,SAAS,MAAM,EAAE;AACpD;AAEO,SAAS,iBAAiB,SAAiB,QAAgB,MAAc,GAAW;AACvF,MAAI,UAAU,KAAK,UAAU,KAAK;AAC9B,UAAM,IAAI,MAAM,sBAAsB;AAAA,EAC1C;AAEA,MAAI,SAAS,KAAK,SAAS,aAAa;AACpC,UAAM,IAAI,MAAM,uBAAuB;AAAA,EAC3C;AAEA,MAAI,MAAM,KAAK,MAAM,QAAQ,QAAQ;AACjC,UAAM,IAAI,MAAM,kBAAkB;AAAA,EACtC;AAEA,QAAM,UAAU,GAAG,GAAG,GAAG,OAAO,SAAS,EAAE,SAAS,IAAI,GAAG,CAAC;AAC5D,QAAM,QAAQ,UAAM,mBAAAA,SAAO,QAAQ,SAAS,EAAE,SAAS,GAAG,GAAG,IAAI,SAAS,EAAE,GAAG,KAAK,CAAC;AAErF,QAAM,MAAM,cAAAC,QAAE,MAAM,CAAC,EAAE,IAAI,OAAK,KAAK,MAAM,QAAS,OAAO,IAAI,EAAG,IAAI,EAAE;AACxE,QAAM,OAAO,cAAAA,QAAE,MAAM,GAAG,IAAI,CAAC,EAAE,IAAI,OAAK,SAAS,QAAQ,CAAC,CAAC,IAAI,KAAK,SAAS,QAAQ,IAAI,CAAC,CAAC,CAAC;AAE5F,MAAI,QAAQ,EAAE,IAAI,CAAC,IAAI,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,GAAG,IAAI,CAAC,GAAG,IAAI,CAAC,GAAG,IAAI,CAAC,IAAI,IAAI,CAAC,IAAI,IAAI,CAAC,KAAK,EAAE;AAC3F,aAAW,CAAC,GAAG,CAAC,KAAK,KAAK,QAAQ,GAAG;AACjC,QAAI,KAAK,GAAG;AACR,WAAK,CAAC,IAAK,KAAK,CAAC,IAAI,MAAQ,SAAS,MAAM,CAAC,CAAC,EAAE,KAAK,CAAC,IAAI,EAAI;AAAA,IAClE,OAAO;AACH,WAAK,CAAC,IAAI,QAAQ,GAAG,EAAE,MAAM,CAAC,CAAC,EAAE,CAAC;AAAA,IACtC;AAAA,EACJ;AAEA,UAAQ,EAAE,IAAI,CAAC,IAAI,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,GAAG,IAAI,CAAC,GAAG,IAAI,CAAC,IAAI,IAAI,CAAC,IAAI,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,CAAC;AACvF,aAAW,CAAC,GAAG,CAAC,KAAK,KAAK,QAAQ,GAAG;AACjC,SAAK,CAAC,IAAI,QAAQ,CAAC,EAAE,MAAM,CAAC,CAAC,EAAE,CAAC;AAAA,EACpC;AAEA,SAAO,GAAG,QAAQ,SAAS,EAAE,SAAS,GAAG,GAAG,CAAC,GAAG,KAAK,IAAI,OAAK,EAAE,SAAS,EAAE,SAAS,GAAG,GAAG,CAAC,EAAE,KAAK,EAAE,CAAC,GAAG,MAAM,SAAS,EAAE,SAAS,GAAG,GAAG,CAAC;AAC7I;;;AC3FO,IAAM,gBAAgB;AACtB,IAAM,mBAAmB;AAEzB,SAAS,qBAA6B;AAEzC,QAAM,SAAS,KAAK,MAAM,KAAK,OAAO,IAAI,IAAY;AACtD,SAAO,iBAAiB,kBAAkB,QAAQ,CAAC;AACvD;AAMO,SAAS,eAAe,IAAqB;AAChD,SAAO,GAAG,CAAC,MAAM,OAAO,cAAc,KAAK,EAAE;AACjD;;;ACbO,SAAS,YAAY,IAA2B;AACnD,UAAQ,yBAAI,eAAe;AAAA,IACvB,KAAK;AACD,aAAO;AAAA,IACX,KAAK;AAAA,IACL,KAAK;AACD,aAAO;AAAA,IACX,KAAK;AACD,aAAO;AAAA,IACX,KAAK;AACD,aAAO;AAAA,IACX,KAAK;AACD,aAAO;AAAA,IAEX;AACI,aAAO;AAAA,EACf;AACJ;","names":["bigInt","_"]} \ No newline at end of file diff --git a/amnet-shared/dist/index.mjs b/amnet-shared/dist/index.mjs index a88051e..fdefb01 100644 --- a/amnet-shared/dist/index.mjs +++ b/amnet-shared/dist/index.mjs @@ -17,83 +17,121 @@ var __spreadValues = (a, b) => { return a; }; var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b)); -var __async = (__this, __arguments, generator) => { - return new Promise((resolve, reject) => { - var fulfilled = (value) => { - try { - step(generator.next(value)); - } catch (e) { - reject(e); - } - }; - var rejected = (value) => { - try { - step(generator.throw(value)); - } catch (e) { - reject(e); - } - }; - var step = (x) => x.done ? resolve(x.value) : Promise.resolve(x.value).then(fulfilled, rejected); - step((generator = generator.apply(__this, __arguments)).next()); - }); -}; // src/api.ts var AMNET_API_VERSION = 1; var MIN_AMNET_API_VERSION = 1; -function performCardIn(server, request, signal) { - return __async(this, null, function* () { - if (server.apiVersion < MIN_AMNET_API_VERSION || server.apiVersion > AMNET_API_VERSION) { - throw new Error("Unsupported server API version"); - } - try { - const response = yield fetch(`${new URL(server.serverAddress).origin}/amnet/signin`, { - method: "POST", - headers: { - "Content-Type": "application/json" - }, - body: JSON.stringify(request), - signal - }); - return response.ok; - } catch (e) { - return false; - } - }); +async function performCardIn(server, request, signal) { + if (server.apiVersion < MIN_AMNET_API_VERSION || server.apiVersion > AMNET_API_VERSION) { + throw new Error("Unsupported server API version"); + } + try { + const response = await fetch(`${new URL(server.serverAddress).origin}/amnet/signin`, { + method: "POST", + headers: { + "Content-Type": "application/json" + }, + body: JSON.stringify(request), + signal + }); + return response.ok; + } catch (e) { + return false; + } } -function fetchServerInfo(serverAddress, abort) { - return __async(this, null, function* () { - try { - const response = yield fetch(`${new URL(serverAddress).origin}/amnet/info`, { - signal: abort - }); - if (!response.ok) { - return null; - } - return __spreadProps(__spreadValues({}, yield response.json()), { - serverAddress - }); - } catch (e) { +async function fetchServerInfo(serverAddress, abort) { + try { + const response = await fetch(`${new URL(serverAddress).origin}/amnet/info`, { + signal: abort + }); + if (!response.ok) { return null; } - }); + return __spreadProps(__spreadValues({}, await response.json()), { + serverAddress + }); + } catch (e) { + return null; + } +} + +// src/card-encoding.ts +import _ from "lodash"; +import bigInt from "big-integer"; +var sbtable = [[[45, 50, 94, 2, 66, 55, 56, 49, 99, 36, 60, 0, 73, 30, 39, 37, 80, 74, 85, 7, 12, 33, 93, 83, 95, 91, 98, 92, 23, 24, 79, 21, 31, 35, 71, 70, 4, 43, 1, 5, 88, 90, 69, 58, 76, 20, 84, 62, 77, 44, 61, 11, 16, 53, 82, 34, 13, 47, 48, 87, 89, 15, 64, 3, 54, 28, 57, 67, 9, 75, 32, 65, 96, 17, 18, 29, 10, 14, 42, 6, 46, 26, 40, 59, 63, 78, 68, 8, 86, 51, 25, 72, 38, 97, 19, 81, 27, 41, 52, 22], [26, 32, 34, 79, 42, 45, 4, 75, 22, 73, 64, 98, 49, 19, 5, 24, 6, 55, 63, 25, 40, 77, 54, 12, 9, 44, 83, 71, 0, 90, 97, 96, 81, 80, 3, 31, 56, 92, 17, 86, 72, 28, 36, 78, 62, 30, 7, 46, 87, 20, 82, 50, 35, 61, 41, 94, 68, 11, 1, 10, 74, 67, 85, 43, 57, 15, 95, 84, 65, 53, 69, 52, 76, 88, 2, 14, 37, 58, 93, 16, 59, 51, 18, 99, 39, 47, 89, 8, 13, 91, 38, 33, 70, 48, 23, 29, 27, 66, 60, 21], [28, 53, 30, 85, 0, 95, 70, 47, 40, 51, 94, 68, 99, 15, 5, 57, 1, 16, 80, 93, 91, 52, 2, 32, 48, 77, 41, 75, 22, 39, 50, 81, 79, 73, 97, 76, 60, 4, 59, 25, 78, 38, 46, 58, 90, 84, 56, 6, 83, 62, 42, 10, 64, 31, 36, 61, 65, 63, 18, 8, 9, 96, 55, 26, 89, 67, 3, 98, 35, 21, 13, 12, 88, 71, 37, 29, 87, 49, 24, 86, 92, 20, 44, 74, 69, 17, 82, 54, 27, 7, 23, 66, 11, 19, 34, 45, 14, 72, 43, 33], [32, 44, 86, 79, 38, 61, 25, 8, 5, 85, 78, 48, 33, 87, 84, 35, 64, 41, 60, 21, 96, 75, 6, 69, 39, 94, 3, 92, 37, 77, 15, 13, 29, 59, 76, 91, 65, 56, 73, 83, 27, 62, 89, 50, 18, 98, 81, 17, 71, 28, 82, 11, 30, 43, 34, 20, 70, 22, 46, 63, 52, 68, 90, 53, 36, 10, 74, 58, 40, 88, 9, 2, 42, 26, 24, 4, 95, 57, 31, 66, 0, 14, 49, 16, 99, 19, 51, 23, 47, 12, 93, 1, 7, 80, 45, 97, 55, 67, 72, 54], [58, 35, 42, 38, 63, 36, 68, 30, 81, 4, 87, 80, 32, 69, 37, 67, 1, 86, 61, 94, 27, 11, 84, 26, 59, 73, 53, 66, 72, 71, 39, 33, 99, 8, 43, 88, 17, 22, 89, 5, 46, 93, 98, 48, 55, 83, 34, 3, 0, 16, 12, 20, 78, 9, 2, 76, 54, 51, 25, 24, 62, 57, 92, 10, 50, 28, 79, 23, 52, 95, 44, 60, 74, 90, 19, 77, 21, 31, 96, 49, 64, 6, 29, 85, 18, 13, 82, 47, 56, 45, 15, 7, 97, 75, 40, 41, 65, 14, 70, 91], [81, 82, 66, 72, 83, 4, 20, 94, 53, 48, 77, 41, 67, 64, 9, 24, 36, 55, 14, 1, 78, 84, 49, 0, 44, 58, 70, 25, 28, 73, 8, 68, 88, 54, 86, 87, 23, 52, 27, 5, 97, 37, 62, 50, 3, 89, 92, 47, 30, 10, 29, 80, 22, 26, 11, 13, 69, 60, 38, 90, 85, 57, 12, 75, 46, 39, 74, 33, 42, 93, 98, 91, 59, 99, 18, 6, 17, 16, 32, 40, 63, 7, 76, 15, 43, 71, 51, 35, 2, 65, 34, 96, 19, 56, 79, 21, 95, 45, 61, 31], [25, 88, 7, 57, 98, 63, 86, 13, 69, 84, 56, 20, 68, 90, 35, 6, 43, 93, 95, 3, 75, 4, 9, 28, 31, 66, 21, 44, 30, 76, 11, 22, 49, 2, 77, 40, 85, 19, 82, 16, 97, 92, 39, 96, 18, 32, 42, 94, 70, 71, 54, 79, 67, 78, 37, 12, 99, 53, 61, 41, 87, 17, 1, 14, 52, 10, 47, 58, 27, 46, 36, 55, 26, 15, 33, 50, 72, 51, 89, 23, 74, 59, 64, 8, 83, 65, 80, 29, 38, 0, 60, 24, 45, 81, 48, 91, 73, 5, 34, 62], [73, 85, 37, 11, 80, 46, 16, 47, 88, 65, 94, 64, 12, 38, 98, 70, 95, 48, 92, 18, 56, 75, 58, 7, 81, 15, 74, 13, 5, 44, 27, 32, 76, 90, 33, 55, 26, 96, 77, 24, 0, 89, 8, 4, 28, 39, 71, 3, 10, 41, 91, 53, 31, 68, 36, 17, 69, 60, 34, 54, 93, 82, 21, 51, 87, 59, 61, 6, 1, 23, 30, 66, 43, 25, 35, 42, 49, 78, 62, 14, 19, 20, 29, 22, 52, 83, 63, 45, 2, 99, 50, 79, 72, 40, 84, 97, 86, 57, 67, 9], [48, 94, 17, 55, 59, 24, 72, 75, 38, 85, 34, 98, 95, 36, 49, 63, 57, 54, 29, 6, 52, 47, 73, 1, 82, 9, 66, 83, 31, 61, 78, 60, 97, 14, 87, 15, 90, 70, 53, 10, 27, 8, 3, 64, 51, 50, 68, 26, 22, 19, 42, 96, 67, 7, 25, 39, 92, 30, 58, 93, 21, 74, 41, 18, 65, 44, 88, 32, 71, 69, 12, 77, 13, 11, 99, 79, 37, 89, 81, 35, 86, 56, 45, 76, 46, 80, 62, 43, 16, 84, 40, 5, 33, 91, 4, 20, 0, 23, 28, 2], [61, 45, 79, 13, 59, 52, 6, 77, 3, 31, 70, 80, 26, 33, 36, 4, 27, 32, 24, 74, 29, 94, 16, 12, 76, 7, 88, 57, 78, 42, 97, 96, 43, 83, 92, 21, 51, 47, 49, 58, 90, 41, 93, 98, 35, 63, 86, 37, 5, 30, 28, 72, 25, 22, 60, 19, 39, 34, 68, 50, 8, 64, 46, 99, 84, 87, 69, 56, 53, 55, 44, 54, 89, 65, 85, 0, 71, 15, 17, 66, 81, 82, 91, 95, 62, 48, 38, 75, 40, 14, 9, 10, 73, 67, 18, 11, 23, 2, 20, 1]], [[95, 90, 61, 38, 18, 7, 83, 39, 79, 14, 48, 21, 81, 44, 78, 50, 56, 91, 12, 86, 99, 98, 43, 63, 73, 87, 42, 72, 15, 68, 97, 23, 88, 69, 2, 51, 19, 58, 59, 22, 20, 29, 82, 11, 75, 70, 9, 71, 27, 30, 47, 89, 92, 60, 46, 76, 93, 54, 1, 96, 94, 57, 40, 62, 41, 3, 28, 64, 37, 74, 67, 16, 65, 53, 5, 36, 24, 45, 32, 33, 10, 85, 26, 4, 84, 77, 35, 13, 6, 8, 17, 80, 25, 55, 52, 66, 49, 34, 0, 31], [18, 14, 70, 43, 74, 45, 94, 36, 40, 6, 31, 46, 15, 47, 13, 19, 72, 61, 99, 21, 17, 92, 88, 78, 73, 90, 0, 96, 20, 28, 25, 51, 50, 77, 29, 16, 54, 12, 58, 38, 71, 23, 42, 83, 65, 60, 10, 33, 22, 76, 95, 32, 57, 5, 59, 67, 68, 3, 91, 85, 26, 62, 41, 1, 53, 82, 34, 24, 87, 27, 89, 75, 56, 30, 81, 7, 8, 4, 64, 66, 9, 63, 35, 52, 80, 93, 69, 84, 55, 86, 48, 98, 79, 97, 49, 44, 39, 11, 37, 2], [76, 16, 73, 29, 34, 14, 36, 90, 58, 70, 46, 2, 91, 59, 63, 32, 84, 40, 78, 38, 19, 37, 0, 31, 8, 44, 94, 39, 10, 66, 42, 1, 21, 88, 82, 97, 33, 4, 99, 74, 89, 62, 25, 87, 77, 43, 50, 95, 64, 23, 47, 93, 65, 27, 12, 71, 9, 72, 60, 18, 7, 22, 79, 24, 96, 45, 49, 98, 57, 11, 5, 86, 3, 80, 26, 51, 17, 85, 54, 67, 48, 35, 53, 41, 28, 13, 20, 92, 83, 69, 6, 68, 75, 52, 61, 30, 81, 56, 15, 55], [0, 62, 25, 61, 56, 87, 54, 27, 75, 49, 18, 69, 17, 71, 40, 6, 90, 80, 23, 26, 68, 24, 10, 21, 47, 88, 36, 55, 15, 22, 48, 12, 83, 99, 46, 67, 59, 29, 58, 73, 78, 97, 19, 33, 51, 98, 65, 91, 16, 4, 63, 41, 3, 70, 30, 8, 89, 34, 72, 60, 9, 95, 50, 2, 66, 53, 44, 85, 28, 5, 92, 43, 64, 96, 74, 77, 45, 52, 14, 42, 1, 32, 20, 76, 86, 82, 94, 7, 39, 13, 31, 11, 84, 93, 35, 37, 38, 57, 79, 81], [78, 8, 59, 25, 69, 15, 63, 3, 57, 5, 50, 96, 41, 66, 80, 81, 7, 45, 60, 74, 79, 32, 27, 58, 56, 82, 11, 47, 17, 85, 53, 40, 95, 84, 76, 92, 18, 71, 64, 51, 67, 91, 22, 34, 65, 31, 73, 93, 68, 75, 77, 37, 43, 12, 20, 99, 2, 1, 19, 35, 44, 55, 90, 9, 0, 6, 33, 89, 24, 14, 97, 10, 48, 61, 23, 54, 98, 86, 88, 94, 46, 70, 28, 36, 16, 30, 4, 39, 26, 38, 87, 52, 83, 49, 62, 42, 72, 29, 13, 21], [20, 88, 35, 5, 85, 98, 11, 78, 62, 83, 79, 80, 40, 14, 91, 8, 7, 69, 71, 61, 49, 38, 64, 82, 0, 47, 84, 95, 2, 50, 77, 41, 97, 36, 33, 81, 46, 21, 73, 48, 31, 92, 54, 89, 87, 60, 90, 10, 76, 45, 99, 52, 3, 44, 39, 43, 18, 16, 63, 12, 28, 70, 86, 6, 4, 24, 59, 30, 96, 65, 22, 56, 74, 23, 32, 75, 53, 93, 15, 67, 66, 17, 29, 25, 42, 37, 57, 9, 72, 68, 26, 34, 27, 51, 19, 58, 55, 94, 13, 1], [72, 53, 79, 61, 30, 33, 25, 75, 8, 55, 14, 6, 22, 93, 18, 77, 4, 74, 44, 36, 82, 94, 2, 5, 62, 54, 28, 3, 63, 97, 65, 7, 84, 73, 39, 92, 67, 91, 24, 45, 15, 81, 19, 78, 80, 64, 34, 43, 32, 87, 52, 95, 89, 37, 10, 23, 20, 68, 42, 47, 59, 58, 49, 71, 40, 85, 13, 31, 12, 57, 96, 90, 56, 41, 48, 9, 99, 35, 98, 26, 1, 46, 11, 69, 27, 83, 60, 50, 21, 70, 0, 88, 29, 86, 76, 16, 66, 38, 51, 17], [3, 68, 86, 94, 81, 90, 85, 32, 65, 52, 50, 42, 80, 78, 26, 93, 57, 58, 69, 82, 92, 27, 11, 67, 95, 41, 21, 88, 35, 17, 19, 15, 22, 62, 40, 76, 63, 59, 37, 55, 75, 9, 24, 89, 56, 53, 23, 60, 25, 6, 1, 71, 16, 7, 10, 44, 8, 12, 87, 64, 54, 72, 20, 33, 70, 79, 14, 97, 4, 99, 45, 39, 2, 77, 98, 74, 49, 30, 13, 61, 66, 73, 47, 43, 96, 83, 18, 91, 28, 48, 38, 34, 31, 36, 29, 0, 84, 46, 5, 51], [71, 84, 25, 70, 77, 56, 61, 47, 72, 27, 54, 89, 9, 46, 95, 59, 42, 98, 63, 69, 48, 16, 97, 14, 66, 83, 87, 68, 17, 2, 15, 79, 31, 1, 57, 12, 33, 36, 0, 40, 21, 50, 76, 41, 10, 13, 44, 5, 53, 4, 38, 35, 55, 96, 81, 91, 90, 64, 34, 51, 6, 28, 32, 39, 75, 18, 93, 24, 78, 7, 52, 43, 49, 37, 74, 8, 58, 65, 92, 67, 85, 20, 94, 88, 80, 86, 19, 60, 3, 11, 30, 45, 29, 22, 26, 73, 99, 23, 62, 82], [67, 91, 46, 33, 76, 3, 96, 23, 9, 68, 49, 63, 1, 92, 58, 62, 69, 77, 70, 75, 71, 94, 51, 55, 50, 52, 0, 88, 18, 16, 73, 6, 12, 87, 93, 79, 84, 57, 48, 41, 20, 47, 15, 42, 54, 81, 7, 30, 34, 56, 29, 8, 98, 5, 45, 64, 83, 74, 22, 82, 80, 95, 2, 72, 44, 31, 86, 78, 13, 10, 28, 89, 60, 35, 61, 19, 14, 85, 4, 43, 11, 40, 26, 99, 39, 32, 90, 17, 24, 37, 36, 21, 25, 53, 97, 59, 27, 38, 65, 66]], [[40, 77, 66, 65, 97, 96, 58, 64, 69, 30, 0, 3, 17, 33, 51, 23, 59, 10, 7, 20, 29, 49, 71, 13, 46, 4, 79, 92, 47, 18, 72, 57, 73, 80, 56, 28, 78, 67, 9, 87, 43, 31, 22, 62, 75, 99, 19, 63, 35, 93, 12, 98, 25, 26, 37, 89, 86, 15, 55, 50, 91, 38, 42, 81, 2, 94, 70, 68, 45, 88, 76, 74, 11, 24, 41, 60, 85, 21, 44, 32, 82, 61, 52, 83, 53, 36, 48, 1, 95, 27, 14, 84, 54, 6, 39, 34, 90, 5, 16, 8], [44, 69, 53, 28, 18, 11, 23, 65, 96, 25, 93, 42, 72, 58, 95, 56, 32, 21, 78, 77, 51, 34, 47, 7, 66, 13, 88, 67, 92, 98, 10, 50, 90, 45, 49, 9, 99, 94, 22, 24, 5, 85, 33, 3, 73, 35, 52, 63, 2, 76, 87, 43, 81, 83, 55, 61, 70, 75, 16, 14, 8, 71, 57, 40, 86, 39, 80, 79, 26, 48, 59, 4, 82, 0, 36, 12, 54, 38, 64, 17, 91, 27, 62, 84, 37, 74, 68, 1, 6, 19, 29, 46, 60, 30, 89, 15, 20, 97, 41, 31], [53, 22, 34, 16, 72, 71, 14, 94, 12, 59, 39, 6, 38, 68, 21, 93, 32, 46, 69, 55, 10, 8, 75, 60, 9, 13, 99, 90, 63, 49, 28, 92, 41, 7, 54, 83, 27, 91, 47, 43, 31, 74, 42, 40, 18, 81, 76, 84, 78, 52, 1, 26, 51, 2, 58, 11, 65, 67, 15, 23, 0, 79, 96, 4, 29, 62, 89, 66, 50, 98, 56, 61, 30, 88, 35, 25, 77, 70, 3, 44, 95, 80, 19, 64, 57, 37, 82, 85, 73, 48, 5, 86, 24, 36, 33, 97, 20, 45, 17, 87], [95, 36, 70, 82, 23, 55, 13, 51, 83, 38, 40, 18, 84, 74, 56, 85, 58, 14, 19, 69, 34, 59, 97, 89, 52, 77, 9, 91, 68, 16, 27, 88, 6, 73, 43, 5, 10, 66, 4, 61, 44, 46, 72, 50, 96, 21, 33, 15, 32, 0, 63, 92, 24, 39, 29, 49, 30, 64, 12, 26, 67, 53, 37, 2, 47, 65, 3, 20, 75, 78, 99, 87, 98, 1, 81, 90, 62, 54, 22, 35, 45, 25, 86, 48, 17, 60, 94, 8, 42, 31, 76, 28, 11, 57, 93, 41, 7, 71, 80, 79], [60, 24, 69, 92, 15, 36, 11, 98, 93, 27, 51, 35, 89, 74, 87, 4, 81, 94, 23, 84, 56, 3, 42, 18, 75, 73, 46, 86, 55, 99, 0, 88, 1, 26, 76, 70, 65, 67, 20, 13, 7, 45, 77, 17, 9, 78, 54, 48, 32, 40, 47, 31, 2, 6, 90, 10, 8, 50, 52, 38, 91, 14, 53, 12, 85, 44, 21, 80, 68, 33, 30, 57, 61, 63, 79, 41, 29, 39, 58, 5, 62, 96, 28, 71, 82, 34, 25, 43, 22, 95, 72, 37, 64, 16, 97, 59, 66, 83, 49, 19], [80, 0, 40, 36, 68, 18, 67, 14, 20, 21, 10, 17, 43, 3, 98, 81, 94, 55, 1, 39, 72, 51, 41, 66, 58, 2, 61, 78, 15, 99, 57, 52, 25, 87, 12, 65, 74, 64, 34, 37, 44, 30, 88, 79, 33, 27, 56, 35, 73, 42, 29, 54, 24, 5, 53, 16, 31, 4, 19, 84, 59, 50, 26, 63, 48, 28, 60, 45, 92, 82, 49, 77, 97, 76, 22, 86, 47, 62, 83, 70, 93, 38, 11, 13, 89, 75, 85, 69, 9, 46, 96, 90, 6, 91, 8, 7, 32, 71, 95, 23], [32, 14, 35, 84, 89, 11, 52, 34, 79, 65, 2, 88, 49, 29, 31, 94, 1, 74, 97, 51, 99, 37, 10, 47, 57, 81, 73, 76, 63, 58, 0, 38, 39, 27, 33, 8, 20, 21, 46, 66, 92, 36, 6, 30, 53, 17, 48, 64, 55, 28, 85, 50, 54, 12, 80, 41, 77, 69, 93, 9, 91, 13, 42, 75, 68, 86, 19, 3, 16, 78, 87, 45, 43, 56, 59, 70, 40, 24, 83, 98, 62, 5, 96, 4, 67, 60, 26, 23, 72, 95, 44, 82, 90, 25, 7, 18, 15, 22, 71, 61], [78, 53, 89, 93, 7, 84, 81, 95, 64, 50, 58, 35, 59, 63, 20, 76, 80, 8, 23, 28, 79, 52, 55, 48, 66, 17, 60, 65, 25, 29, 30, 9, 73, 39, 69, 3, 98, 22, 15, 87, 4, 37, 43, 5, 11, 83, 91, 40, 51, 33, 12, 92, 6, 67, 41, 94, 45, 88, 56, 36, 0, 68, 19, 54, 70, 26, 72, 77, 32, 34, 97, 71, 99, 75, 61, 31, 86, 82, 46, 2, 44, 96, 49, 74, 10, 62, 24, 16, 1, 38, 27, 14, 18, 85, 13, 57, 90, 21, 42, 47], [26, 30, 60, 78, 75, 48, 73, 52, 51, 57, 63, 90, 27, 36, 83, 81, 41, 44, 82, 37, 10, 64, 91, 4, 59, 95, 21, 24, 77, 56, 43, 38, 62, 55, 92, 0, 94, 20, 86, 66, 35, 80, 53, 25, 17, 18, 49, 76, 23, 89, 13, 15, 68, 8, 22, 46, 1, 42, 3, 34, 98, 88, 69, 31, 50, 65, 84, 32, 47, 61, 9, 19, 99, 85, 11, 79, 70, 2, 74, 14, 87, 7, 72, 5, 12, 58, 67, 39, 16, 71, 54, 6, 45, 93, 96, 28, 97, 29, 33, 40], [77, 66, 20, 30, 42, 23, 0, 49, 7, 64, 54, 27, 96, 97, 39, 84, 2, 51, 71, 17, 4, 92, 94, 95, 67, 69, 73, 75, 86, 37, 74, 50, 11, 79, 29, 15, 56, 43, 22, 83, 81, 61, 14, 3, 36, 44, 58, 10, 62, 19, 72, 80, 65, 24, 18, 5, 40, 90, 33, 9, 47, 76, 8, 59, 35, 91, 99, 13, 70, 88, 55, 16, 31, 28, 85, 45, 60, 25, 87, 82, 93, 12, 34, 68, 63, 26, 46, 48, 21, 52, 1, 78, 98, 38, 6, 32, 89, 53, 41, 57]], [[77, 99, 47, 64, 26, 63, 50, 81, 23, 45, 49, 36, 43, 56, 39, 12, 86, 62, 2, 98, 60, 94, 75, 9, 20, 74, 48, 28, 4, 84, 61, 31, 54, 15, 40, 7, 87, 38, 80, 6, 37, 46, 1, 55, 88, 73, 95, 33, 92, 18, 25, 66, 57, 27, 42, 35, 91, 51, 13, 90, 41, 83, 68, 53, 19, 3, 72, 89, 65, 70, 71, 8, 97, 59, 96, 52, 79, 22, 14, 69, 32, 93, 58, 29, 21, 76, 34, 5, 17, 67, 11, 78, 16, 0, 44, 30, 10, 24, 85, 82], [58, 62, 7, 39, 34, 69, 67, 73, 37, 59, 71, 66, 46, 57, 44, 51, 26, 85, 11, 28, 54, 47, 82, 21, 83, 76, 94, 16, 90, 95, 75, 55, 6, 22, 72, 74, 50, 40, 10, 19, 8, 53, 33, 98, 45, 87, 91, 13, 35, 70, 14, 38, 84, 99, 56, 30, 12, 89, 25, 97, 63, 65, 81, 92, 18, 29, 80, 61, 93, 43, 49, 52, 23, 31, 32, 4, 48, 3, 0, 78, 96, 64, 41, 88, 24, 5, 9, 15, 77, 86, 68, 1, 17, 79, 60, 36, 42, 2, 20, 27], [58, 62, 7, 39, 34, 69, 67, 73, 37, 59, 71, 66, 46, 57, 44, 51, 26, 85, 11, 28, 54, 47, 82, 21, 83, 76, 94, 16, 90, 95, 75, 55, 6, 22, 72, 74, 50, 40, 10, 19, 8, 53, 33, 98, 45, 87, 91, 13, 35, 70, 14, 38, 84, 99, 56, 30, 12, 89, 25, 97, 63, 65, 81, 92, 18, 29, 80, 61, 93, 43, 49, 52, 23, 31, 32, 4, 48, 3, 0, 78, 96, 64, 41, 88, 24, 5, 9, 15, 77, 86, 68, 1, 17, 79, 60, 36, 42, 2, 20, 27], [91, 43, 77, 69, 16, 96, 47, 34, 49, 15, 73, 84, 85, 22, 88, 95, 2, 80, 57, 33, 32, 41, 25, 14, 58, 9, 20, 65, 48, 97, 79, 89, 66, 63, 46, 83, 19, 92, 55, 18, 38, 0, 21, 50, 45, 62, 29, 26, 52, 28, 8, 6, 75, 86, 44, 81, 36, 90, 70, 30, 71, 39, 82, 87, 76, 1, 23, 5, 60, 98, 67, 53, 93, 72, 42, 74, 51, 4, 31, 59, 61, 7, 24, 56, 37, 54, 3, 11, 27, 40, 10, 64, 94, 35, 78, 68, 99, 17, 12, 13], [73, 70, 39, 9, 77, 61, 80, 10, 13, 92, 38, 4, 48, 57, 25, 72, 49, 51, 99, 97, 85, 36, 22, 15, 8, 34, 33, 76, 26, 45, 83, 59, 28, 96, 90, 47, 68, 88, 44, 6, 98, 12, 24, 46, 2, 54, 5, 58, 30, 63, 1, 18, 93, 67, 7, 50, 31, 16, 40, 56, 23, 86, 11, 52, 55, 75, 71, 27, 37, 87, 84, 65, 82, 29, 0, 14, 41, 35, 64, 21, 3, 95, 17, 60, 81, 74, 19, 91, 94, 32, 69, 53, 42, 89, 79, 43, 66, 20, 78, 62], [23, 78, 67, 41, 9, 77, 59, 72, 25, 82, 65, 89, 28, 37, 54, 70, 98, 33, 31, 44, 6, 17, 26, 73, 21, 36, 4, 2, 79, 95, 81, 50, 18, 34, 61, 0, 93, 24, 8, 66, 55, 62, 56, 30, 84, 58, 7, 88, 85, 64, 97, 39, 49, 3, 20, 42, 80, 96, 13, 63, 43, 60, 47, 90, 51, 14, 53, 1, 86, 57, 12, 19, 10, 45, 38, 68, 35, 87, 75, 5, 69, 27, 32, 91, 11, 99, 46, 29, 92, 22, 76, 15, 16, 48, 71, 74, 52, 94, 83, 40], [87, 89, 35, 98, 44, 21, 29, 83, 0, 77, 34, 60, 85, 64, 28, 58, 39, 36, 95, 22, 67, 30, 86, 57, 5, 81, 84, 26, 53, 62, 13, 90, 2, 88, 4, 46, 97, 73, 79, 43, 59, 72, 54, 32, 82, 10, 55, 38, 47, 12, 51, 1, 76, 48, 7, 14, 23, 20, 31, 18, 17, 15, 37, 42, 49, 68, 25, 93, 91, 40, 92, 50, 52, 70, 33, 80, 19, 96, 61, 75, 71, 99, 74, 9, 41, 66, 63, 8, 6, 24, 65, 56, 45, 69, 27, 16, 3, 78, 94, 11], [99, 6, 38, 11, 34, 28, 86, 57, 55, 78, 25, 95, 13, 63, 91, 14, 83, 1, 45, 17, 93, 76, 46, 79, 27, 85, 96, 58, 59, 44, 87, 65, 97, 22, 0, 51, 49, 52, 47, 67, 24, 88, 62, 50, 72, 3, 31, 82, 68, 42, 81, 23, 32, 98, 73, 60, 37, 54, 41, 80, 66, 18, 92, 4, 5, 94, 77, 39, 69, 16, 35, 7, 40, 30, 61, 26, 56, 64, 9, 71, 19, 21, 75, 84, 43, 53, 33, 29, 74, 36, 90, 2, 20, 15, 10, 48, 89, 70, 8, 12], [4, 28, 8, 72, 74, 31, 66, 0, 27, 54, 61, 23, 51, 73, 96, 32, 98, 41, 88, 95, 36, 22, 13, 38, 70, 84, 12, 7, 10, 60, 68, 33, 11, 35, 79, 42, 16, 62, 57, 24, 44, 94, 25, 48, 86, 97, 87, 49, 92, 71, 21, 1, 81, 5, 17, 85, 6, 75, 80, 34, 20, 30, 90, 69, 18, 89, 93, 56, 91, 40, 77, 52, 53, 14, 65, 45, 76, 2, 9, 29, 3, 26, 59, 55, 83, 46, 67, 47, 39, 50, 58, 63, 99, 15, 37, 43, 82, 64, 78, 19], [11, 94, 1, 93, 59, 91, 89, 51, 61, 81, 13, 29, 27, 58, 26, 3, 53, 69, 73, 21, 39, 12, 5, 18, 98, 74, 9, 96, 28, 65, 23, 4, 41, 72, 88, 34, 83, 54, 7, 15, 38, 84, 90, 52, 77, 48, 64, 60, 20, 79, 19, 66, 97, 30, 87, 45, 40, 36, 14, 86, 32, 33, 57, 16, 43, 42, 50, 10, 44, 76, 37, 6, 56, 31, 68, 99, 2, 17, 22, 35, 92, 85, 46, 75, 71, 67, 95, 78, 8, 63, 82, 25, 80, 24, 47, 49, 0, 70, 62, 55]], [[93, 99, 51, 49, 71, 64, 35, 42, 88, 17, 67, 92, 4, 12, 68, 13, 47, 7, 56, 14, 19, 53, 80, 85, 23, 5, 39, 6, 26, 89, 27, 54, 63, 73, 70, 33, 36, 3, 86, 58, 18, 2, 25, 21, 10, 34, 81, 94, 75, 98, 37, 46, 9, 95, 60, 74, 87, 78, 20, 24, 57, 0, 30, 83, 72, 61, 11, 32, 43, 82, 65, 69, 59, 62, 38, 76, 22, 16, 15, 45, 48, 79, 50, 90, 40, 1, 29, 77, 91, 31, 84, 96, 8, 52, 97, 41, 28, 44, 55, 66], [64, 71, 19, 27, 43, 95, 77, 16, 35, 81, 74, 29, 6, 86, 18, 37, 99, 46, 15, 87, 28, 63, 1, 65, 3, 79, 50, 12, 78, 84, 8, 88, 98, 69, 42, 0, 56, 32, 92, 83, 30, 59, 80, 9, 20, 89, 47, 23, 33, 34, 82, 24, 97, 60, 22, 90, 51, 76, 10, 94, 21, 91, 70, 49, 66, 14, 75, 2, 7, 13, 40, 93, 48, 36, 53, 72, 67, 62, 85, 17, 57, 58, 5, 25, 41, 31, 44, 73, 61, 26, 38, 54, 96, 39, 4, 68, 11, 52, 45, 55], [49, 88, 62, 73, 34, 15, 95, 68, 98, 5, 61, 35, 23, 45, 78, 64, 97, 70, 96, 65, 74, 16, 94, 37, 80, 56, 48, 28, 59, 1, 75, 4, 71, 47, 83, 93, 69, 21, 60, 38, 39, 19, 40, 82, 55, 7, 52, 18, 43, 54, 2, 77, 66, 90, 44, 32, 89, 3, 24, 6, 99, 17, 86, 29, 30, 22, 50, 81, 41, 42, 0, 9, 53, 58, 57, 25, 20, 12, 26, 51, 92, 87, 36, 31, 85, 63, 14, 8, 91, 11, 79, 27, 76, 84, 67, 33, 72, 13, 10, 46], [45, 15, 69, 88, 51, 28, 34, 80, 30, 42, 38, 90, 47, 17, 84, 49, 21, 55, 46, 96, 37, 97, 72, 85, 94, 29, 10, 66, 76, 82, 18, 86, 87, 25, 43, 92, 19, 89, 2, 93, 98, 40, 48, 53, 75, 99, 11, 62, 12, 60, 3, 24, 4, 6, 63, 81, 41, 20, 68, 9, 57, 52, 0, 44, 14, 16, 91, 27, 79, 73, 59, 61, 78, 7, 67, 1, 70, 83, 74, 64, 26, 95, 54, 65, 33, 39, 5, 50, 36, 35, 13, 23, 58, 71, 32, 77, 31, 22, 56, 8], [41, 43, 66, 69, 22, 23, 71, 2, 33, 38, 86, 51, 55, 59, 82, 96, 45, 97, 73, 34, 70, 21, 8, 58, 84, 90, 24, 25, 32, 78, 17, 27, 47, 68, 37, 72, 63, 77, 87, 89, 50, 16, 83, 54, 12, 56, 64, 62, 39, 92, 91, 53, 29, 76, 52, 94, 42, 81, 20, 98, 40, 79, 44, 10, 31, 0, 57, 19, 75, 67, 93, 6, 7, 11, 74, 26, 85, 5, 1, 49, 4, 61, 95, 3, 36, 9, 14, 13, 15, 48, 80, 46, 30, 65, 99, 18, 60, 88, 35, 28], [5, 56, 10, 81, 42, 35, 12, 94, 34, 13, 8, 0, 49, 17, 7, 69, 30, 1, 65, 14, 39, 2, 58, 76, 54, 31, 50, 46, 11, 27, 22, 61, 74, 64, 91, 18, 48, 63, 71, 57, 95, 87, 47, 67, 77, 53, 88, 23, 3, 83, 29, 86, 43, 60, 70, 78, 21, 99, 36, 66, 20, 62, 85, 4, 80, 98, 79, 82, 97, 15, 96, 52, 51, 6, 40, 93, 28, 41, 72, 45, 68, 16, 32, 75, 84, 89, 26, 55, 9, 59, 73, 24, 25, 33, 37, 19, 90, 44, 38, 92], [62, 28, 97, 69, 65, 46, 27, 96, 29, 73, 89, 42, 16, 36, 44, 63, 80, 60, 11, 54, 87, 92, 75, 81, 57, 26, 70, 49, 76, 10, 95, 84, 56, 22, 20, 9, 21, 61, 1, 47, 34, 19, 66, 0, 33, 91, 45, 3, 2, 90, 88, 43, 51, 12, 7, 18, 24, 85, 86, 8, 78, 38, 55, 30, 6, 35, 15, 93, 14, 99, 98, 82, 52, 74, 4, 50, 79, 37, 77, 17, 41, 71, 58, 53, 68, 39, 67, 25, 5, 83, 94, 13, 48, 32, 23, 59, 31, 64, 72, 40], [93, 20, 18, 22, 94, 27, 39, 59, 4, 11, 6, 75, 98, 62, 63, 81, 44, 53, 25, 95, 74, 57, 76, 5, 70, 60, 99, 12, 56, 85, 41, 67, 46, 19, 28, 1, 23, 80, 32, 68, 31, 51, 82, 55, 78, 77, 58, 69, 38, 87, 91, 79, 96, 52, 47, 73, 83, 89, 65, 3, 92, 14, 43, 66, 61, 37, 84, 54, 33, 88, 35, 71, 42, 90, 72, 50, 7, 40, 0, 24, 9, 29, 49, 45, 15, 21, 86, 64, 16, 36, 34, 17, 26, 10, 2, 13, 8, 97, 30, 48], [33, 3, 7, 64, 74, 23, 42, 25, 68, 85, 5, 8, 83, 17, 56, 79, 70, 73, 15, 6, 36, 18, 94, 97, 72, 22, 11, 96, 40, 58, 66, 49, 62, 86, 78, 67, 26, 98, 90, 48, 14, 2, 82, 91, 9, 76, 69, 44, 50, 47, 53, 71, 92, 12, 59, 37, 19, 60, 39, 13, 77, 16, 55, 41, 84, 31, 65, 27, 99, 51, 4, 45, 80, 46, 57, 21, 28, 81, 54, 29, 61, 88, 52, 43, 75, 20, 1, 10, 0, 35, 30, 32, 95, 38, 63, 87, 89, 24, 34, 93], [37, 25, 50, 66, 86, 23, 76, 27, 83, 97, 89, 35, 32, 41, 33, 87, 14, 59, 48, 61, 52, 3, 73, 67, 24, 56, 93, 22, 7, 70, 77, 28, 91, 30, 68, 29, 60, 8, 94, 13, 43, 17, 88, 57, 81, 34, 15, 95, 79, 96, 72, 84, 55, 46, 58, 10, 12, 38, 11, 99, 53, 42, 65, 44, 31, 21, 82, 6, 92, 26, 51, 5, 39, 63, 40, 9, 49, 18, 78, 80, 71, 74, 90, 2, 54, 47, 85, 75, 69, 45, 0, 16, 19, 1, 64, 98, 4, 62, 36, 20]]]; +var sbtable2 = [[3, 5, 8, 6, 0, 9, 7, 1, 2, 4], [1, 3, 9, 4, 2, 0, 8, 7, 5, 6], [0, 5, 1, 7, 9, 8, 6, 2, 3, 4], [6, 4, 7, 8, 3, 0, 9, 5, 2, 1], [2, 3, 8, 1, 9, 7, 6, 0, 4, 5], [3, 4, 1, 7, 2, 8, 6, 0, 9, 5], [6, 1, 8, 3, 0, 4, 2, 7, 5, 9], [9, 3, 7, 5, 2, 4, 0, 6, 1, 8], [6, 1, 5, 3, 0, 8, 7, 4, 2, 9], [9, 7, 4, 5, 1, 2, 3, 0, 8, 6]]; +var ibtable = [[[11, 38, 3, 63, 36, 39, 79, 19, 87, 68, 76, 51, 20, 56, 77, 61, 52, 73, 74, 94, 45, 31, 99, 28, 29, 90, 81, 96, 65, 75, 13, 32, 70, 21, 55, 33, 9, 15, 92, 14, 82, 97, 78, 37, 49, 0, 80, 57, 58, 7, 1, 89, 98, 53, 64, 5, 6, 66, 43, 83, 10, 50, 47, 84, 62, 71, 4, 67, 86, 42, 35, 34, 91, 12, 17, 69, 44, 48, 85, 30, 16, 95, 54, 23, 46, 18, 88, 59, 40, 60, 41, 25, 27, 22, 2, 24, 72, 93, 26, 8], [28, 58, 74, 34, 6, 14, 16, 46, 87, 24, 59, 57, 23, 88, 75, 65, 79, 38, 82, 13, 49, 99, 8, 94, 15, 19, 0, 96, 41, 95, 45, 35, 1, 91, 2, 52, 42, 76, 90, 84, 20, 54, 4, 63, 25, 5, 47, 85, 93, 12, 51, 81, 71, 69, 22, 17, 36, 64, 77, 80, 98, 53, 44, 18, 10, 68, 97, 61, 56, 70, 92, 27, 40, 9, 60, 7, 72, 21, 43, 3, 33, 32, 50, 26, 67, 62, 39, 48, 73, 86, 29, 89, 37, 78, 55, 66, 31, 30, 11, 83], [4, 16, 22, 66, 37, 14, 47, 89, 59, 60, 51, 92, 71, 70, 96, 13, 17, 85, 58, 93, 81, 69, 28, 90, 78, 39, 63, 88, 0, 75, 2, 53, 23, 99, 94, 68, 54, 74, 41, 29, 8, 26, 50, 98, 82, 95, 42, 7, 24, 77, 30, 9, 21, 1, 87, 62, 46, 15, 43, 38, 36, 55, 49, 57, 52, 56, 91, 65, 11, 84, 6, 73, 97, 33, 83, 27, 35, 25, 40, 32, 18, 31, 86, 48, 45, 3, 79, 76, 72, 64, 44, 20, 80, 19, 10, 5, 61, 34, 67, 12], [80, 91, 71, 26, 75, 8, 22, 92, 7, 70, 65, 51, 89, 31, 81, 30, 83, 47, 44, 85, 55, 19, 57, 87, 74, 6, 73, 40, 49, 32, 52, 78, 0, 12, 54, 15, 64, 28, 4, 24, 68, 17, 72, 53, 1, 94, 58, 88, 11, 82, 43, 86, 60, 63, 99, 96, 37, 77, 67, 33, 18, 5, 41, 59, 16, 36, 79, 97, 61, 23, 56, 48, 98, 38, 66, 21, 34, 29, 10, 3, 93, 46, 50, 39, 14, 9, 2, 13, 69, 42, 62, 35, 27, 90, 25, 76, 20, 95, 45, 84], [48, 16, 54, 47, 9, 39, 81, 91, 33, 53, 63, 21, 50, 85, 97, 90, 49, 36, 84, 74, 51, 76, 37, 67, 59, 58, 23, 20, 65, 82, 7, 77, 12, 31, 46, 1, 5, 14, 3, 30, 94, 95, 2, 34, 70, 89, 40, 87, 43, 79, 64, 57, 68, 26, 56, 44, 88, 61, 0, 24, 71, 18, 60, 4, 80, 96, 27, 15, 6, 13, 98, 29, 28, 25, 72, 93, 55, 75, 52, 66, 11, 8, 86, 45, 22, 83, 17, 10, 35, 38, 73, 99, 62, 41, 19, 69, 78, 92, 42, 32], [23, 19, 88, 44, 5, 39, 75, 81, 30, 14, 49, 54, 62, 55, 18, 83, 77, 76, 74, 92, 6, 95, 52, 36, 15, 27, 53, 38, 28, 50, 48, 99, 78, 67, 90, 87, 16, 41, 58, 65, 79, 11, 68, 84, 24, 97, 64, 47, 9, 22, 43, 86, 37, 8, 33, 17, 93, 61, 25, 72, 57, 98, 42, 80, 13, 89, 2, 12, 31, 56, 26, 85, 3, 29, 66, 63, 82, 10, 20, 94, 51, 0, 1, 4, 21, 60, 34, 35, 32, 45, 59, 71, 46, 69, 7, 96, 91, 40, 70, 73], [89, 62, 33, 19, 21, 97, 15, 2, 83, 22, 65, 30, 55, 7, 63, 73, 39, 61, 44, 37, 11, 26, 31, 79, 91, 0, 72, 68, 23, 87, 28, 24, 45, 74, 98, 14, 70, 54, 88, 42, 35, 59, 46, 16, 27, 92, 69, 66, 94, 32, 75, 77, 64, 57, 50, 71, 10, 3, 67, 81, 90, 58, 99, 5, 82, 85, 25, 52, 12, 8, 48, 49, 76, 96, 80, 20, 29, 34, 53, 51, 86, 93, 38, 84, 9, 36, 6, 60, 1, 78, 13, 95, 41, 17, 47, 18, 43, 40, 4, 56], [40, 68, 88, 47, 43, 28, 67, 23, 42, 99, 48, 3, 12, 27, 79, 25, 6, 55, 19, 80, 81, 62, 83, 69, 39, 73, 36, 30, 44, 82, 70, 52, 31, 34, 58, 74, 54, 2, 13, 45, 93, 49, 75, 72, 29, 87, 5, 7, 17, 76, 90, 63, 84, 51, 59, 35, 20, 97, 22, 65, 57, 66, 78, 86, 11, 9, 71, 98, 53, 56, 15, 46, 92, 0, 26, 21, 32, 38, 77, 91, 4, 24, 61, 85, 94, 1, 96, 64, 8, 41, 33, 50, 18, 60, 10, 16, 37, 95, 14, 89], [96, 23, 99, 42, 94, 91, 19, 53, 41, 25, 39, 73, 70, 72, 33, 35, 88, 2, 63, 49, 95, 60, 48, 97, 5, 54, 47, 40, 98, 18, 57, 28, 67, 92, 10, 79, 13, 76, 8, 55, 90, 62, 50, 87, 65, 82, 84, 21, 0, 14, 45, 44, 20, 38, 17, 3, 81, 16, 58, 4, 31, 29, 86, 15, 43, 64, 26, 52, 46, 69, 37, 68, 6, 22, 61, 7, 83, 71, 30, 75, 85, 78, 24, 27, 89, 9, 80, 34, 66, 77, 36, 93, 56, 59, 1, 12, 51, 32, 11, 74], [75, 99, 97, 8, 15, 48, 6, 25, 60, 90, 91, 95, 23, 3, 89, 77, 22, 78, 94, 55, 98, 35, 53, 96, 18, 52, 12, 16, 50, 20, 49, 9, 17, 13, 57, 44, 14, 47, 86, 56, 88, 41, 29, 32, 70, 1, 62, 37, 85, 38, 59, 36, 5, 68, 71, 69, 67, 27, 39, 4, 54, 0, 84, 45, 61, 73, 79, 93, 58, 66, 10, 76, 51, 92, 19, 87, 24, 7, 28, 2, 11, 80, 81, 33, 64, 74, 46, 65, 26, 72, 40, 82, 34, 42, 21, 83, 31, 30, 43, 63]], [[98, 58, 34, 65, 83, 74, 88, 5, 89, 46, 80, 43, 18, 87, 9, 28, 71, 90, 4, 36, 40, 11, 39, 31, 76, 92, 82, 48, 66, 41, 49, 99, 78, 79, 97, 86, 75, 68, 3, 7, 62, 64, 26, 22, 13, 77, 54, 50, 10, 96, 15, 35, 94, 73, 57, 93, 16, 61, 37, 38, 53, 2, 63, 23, 67, 72, 95, 70, 29, 33, 45, 47, 27, 24, 69, 44, 55, 85, 14, 8, 91, 12, 42, 6, 84, 81, 19, 25, 32, 51, 1, 17, 52, 56, 60, 0, 59, 30, 21, 20], [26, 63, 99, 57, 77, 53, 9, 75, 76, 80, 46, 97, 37, 14, 1, 12, 35, 20, 0, 15, 28, 19, 48, 41, 67, 30, 60, 69, 29, 34, 73, 10, 51, 47, 66, 82, 7, 98, 39, 96, 8, 62, 42, 3, 95, 5, 11, 13, 90, 94, 32, 31, 83, 64, 36, 88, 72, 52, 38, 54, 45, 17, 61, 81, 78, 44, 79, 55, 56, 86, 2, 40, 16, 24, 4, 71, 49, 33, 23, 92, 84, 74, 65, 43, 87, 59, 89, 68, 22, 70, 25, 58, 21, 85, 6, 50, 27, 93, 91, 18], [22, 31, 11, 72, 37, 70, 90, 60, 24, 56, 28, 69, 54, 85, 5, 98, 1, 76, 59, 20, 86, 32, 61, 49, 63, 42, 74, 53, 84, 3, 95, 23, 15, 36, 4, 81, 6, 21, 19, 27, 17, 83, 30, 45, 25, 65, 10, 50, 80, 66, 46, 75, 93, 82, 78, 99, 97, 68, 8, 13, 58, 94, 41, 14, 48, 52, 29, 79, 91, 89, 9, 55, 57, 2, 39, 92, 0, 44, 18, 62, 73, 96, 34, 88, 16, 77, 71, 43, 33, 40, 7, 12, 87, 51, 26, 47, 64, 35, 67, 38], [0, 80, 63, 52, 49, 69, 15, 87, 55, 60, 22, 91, 31, 89, 78, 28, 48, 12, 10, 42, 82, 23, 29, 18, 21, 2, 19, 7, 68, 37, 54, 90, 81, 43, 57, 94, 26, 95, 96, 88, 14, 51, 79, 71, 66, 76, 34, 24, 30, 9, 62, 44, 77, 65, 6, 27, 4, 97, 38, 36, 59, 3, 1, 50, 72, 46, 64, 35, 20, 11, 53, 13, 58, 39, 74, 8, 83, 75, 40, 98, 17, 99, 85, 32, 92, 67, 84, 5, 25, 56, 16, 47, 70, 93, 86, 61, 73, 41, 45, 33], [64, 57, 56, 7, 86, 9, 65, 16, 1, 63, 71, 26, 53, 98, 69, 5, 84, 28, 36, 58, 54, 99, 42, 74, 68, 3, 88, 22, 82, 97, 85, 45, 21, 66, 43, 59, 83, 51, 89, 87, 31, 12, 95, 52, 60, 17, 80, 27, 72, 93, 10, 39, 91, 30, 75, 61, 24, 8, 23, 2, 18, 73, 94, 6, 38, 44, 13, 40, 48, 4, 81, 37, 96, 46, 19, 49, 34, 50, 0, 20, 14, 15, 25, 92, 33, 29, 77, 90, 78, 67, 62, 41, 35, 47, 79, 32, 11, 70, 76, 55], [24, 99, 28, 52, 64, 3, 63, 16, 15, 87, 47, 6, 59, 98, 13, 78, 57, 81, 56, 94, 0, 37, 70, 73, 65, 83, 90, 92, 60, 82, 67, 40, 74, 34, 91, 2, 33, 85, 21, 54, 12, 31, 84, 55, 53, 49, 36, 25, 39, 20, 29, 93, 51, 76, 42, 96, 71, 86, 95, 66, 45, 19, 8, 58, 22, 69, 80, 79, 89, 17, 61, 18, 88, 38, 72, 75, 48, 30, 7, 10, 11, 35, 23, 9, 26, 4, 62, 44, 1, 43, 46, 14, 41, 77, 97, 27, 68, 32, 5, 50], [90, 80, 22, 27, 16, 23, 11, 31, 8, 75, 54, 82, 68, 66, 10, 40, 95, 99, 14, 42, 56, 88, 12, 55, 38, 6, 79, 84, 26, 92, 4, 67, 48, 5, 46, 77, 19, 53, 97, 34, 64, 73, 58, 47, 18, 39, 81, 59, 74, 62, 87, 98, 50, 1, 25, 9, 72, 69, 61, 60, 86, 3, 24, 28, 45, 30, 96, 36, 57, 83, 89, 63, 0, 33, 17, 7, 94, 15, 43, 2, 44, 41, 20, 85, 32, 65, 93, 49, 91, 52, 71, 37, 35, 13, 21, 51, 70, 29, 78, 76], [95, 50, 72, 0, 68, 98, 49, 53, 56, 41, 54, 22, 57, 78, 66, 31, 52, 29, 86, 30, 62, 26, 32, 46, 42, 48, 14, 21, 88, 94, 77, 92, 7, 63, 91, 28, 93, 38, 90, 71, 34, 25, 11, 83, 55, 70, 97, 82, 89, 76, 10, 99, 9, 45, 60, 39, 44, 16, 17, 37, 47, 79, 33, 36, 59, 8, 80, 23, 1, 18, 64, 51, 61, 81, 75, 40, 35, 73, 13, 65, 12, 4, 19, 85, 96, 6, 2, 58, 27, 43, 5, 87, 20, 15, 3, 24, 84, 67, 74, 69], [38, 33, 29, 88, 49, 47, 60, 69, 75, 12, 44, 89, 35, 45, 23, 30, 21, 28, 65, 86, 81, 40, 93, 97, 67, 2, 94, 9, 61, 92, 90, 32, 62, 36, 58, 51, 37, 73, 50, 63, 39, 43, 16, 71, 46, 91, 13, 7, 20, 72, 41, 59, 70, 48, 10, 52, 5, 34, 76, 15, 87, 6, 98, 18, 57, 77, 24, 79, 27, 19, 3, 0, 8, 95, 74, 64, 42, 4, 68, 31, 84, 54, 99, 25, 1, 80, 85, 26, 83, 11, 56, 55, 78, 66, 82, 14, 53, 22, 17, 96], [26, 12, 62, 5, 78, 53, 31, 46, 51, 8, 69, 80, 32, 68, 76, 42, 29, 87, 28, 75, 40, 91, 58, 7, 88, 92, 82, 96, 70, 50, 47, 65, 85, 3, 48, 73, 90, 89, 97, 84, 81, 39, 43, 79, 64, 54, 2, 41, 38, 10, 24, 22, 25, 93, 44, 23, 49, 37, 14, 95, 72, 74, 15, 11, 55, 98, 99, 0, 9, 16, 18, 20, 63, 30, 57, 19, 4, 17, 67, 35, 60, 45, 59, 56, 36, 77, 66, 33, 27, 71, 86, 1, 13, 34, 21, 61, 6, 94, 52, 83]], [[10, 87, 64, 11, 25, 97, 93, 18, 99, 38, 17, 72, 50, 23, 90, 57, 98, 12, 29, 46, 19, 77, 42, 15, 73, 52, 53, 89, 35, 20, 9, 41, 79, 13, 95, 48, 85, 54, 61, 94, 0, 74, 62, 40, 78, 68, 24, 28, 86, 21, 59, 14, 82, 84, 92, 58, 34, 31, 6, 16, 75, 81, 43, 47, 7, 3, 2, 37, 67, 8, 66, 22, 30, 32, 71, 44, 70, 1, 36, 26, 33, 63, 80, 83, 91, 76, 56, 39, 69, 55, 96, 60, 27, 49, 65, 88, 5, 4, 51, 45], [73, 87, 48, 43, 71, 40, 88, 23, 60, 35, 30, 5, 75, 25, 59, 95, 58, 79, 4, 89, 96, 17, 38, 6, 39, 9, 68, 81, 3, 90, 93, 99, 16, 42, 21, 45, 74, 84, 77, 65, 63, 98, 11, 51, 0, 33, 91, 22, 69, 34, 31, 20, 46, 2, 76, 54, 15, 62, 13, 70, 92, 55, 82, 47, 78, 7, 24, 27, 86, 1, 56, 61, 12, 44, 85, 57, 49, 19, 18, 67, 66, 52, 72, 53, 83, 41, 64, 50, 26, 94, 32, 80, 28, 10, 37, 14, 8, 97, 29, 36], [60, 50, 53, 78, 63, 90, 11, 33, 21, 24, 20, 55, 8, 25, 6, 58, 3, 98, 44, 82, 96, 14, 1, 59, 92, 75, 51, 36, 30, 64, 72, 40, 16, 94, 2, 74, 93, 85, 12, 10, 43, 32, 42, 39, 79, 97, 17, 38, 89, 29, 68, 52, 49, 0, 34, 19, 70, 84, 54, 9, 23, 71, 65, 28, 83, 56, 67, 57, 13, 18, 77, 5, 4, 88, 41, 22, 46, 76, 48, 61, 81, 45, 86, 35, 47, 87, 91, 99, 73, 66, 27, 37, 31, 15, 7, 80, 62, 95, 69, 26], [49, 73, 63, 66, 38, 35, 32, 96, 87, 26, 36, 92, 58, 6, 17, 47, 29, 84, 11, 18, 67, 45, 78, 4, 52, 81, 59, 30, 91, 54, 56, 89, 48, 46, 20, 79, 1, 62, 9, 53, 10, 95, 88, 34, 40, 80, 41, 64, 83, 55, 43, 7, 24, 61, 77, 5, 14, 93, 16, 21, 85, 39, 76, 50, 57, 65, 37, 60, 28, 19, 2, 97, 42, 33, 13, 68, 90, 25, 69, 99, 98, 74, 3, 8, 12, 15, 82, 71, 31, 23, 75, 27, 51, 94, 86, 0, 44, 22, 72, 70], [30, 32, 52, 21, 15, 79, 53, 40, 56, 44, 55, 6, 63, 39, 61, 4, 93, 43, 23, 99, 38, 66, 88, 18, 1, 86, 33, 9, 82, 76, 70, 51, 48, 69, 85, 11, 5, 91, 59, 77, 49, 75, 22, 87, 65, 41, 26, 50, 47, 98, 57, 10, 58, 62, 46, 28, 20, 71, 78, 95, 0, 72, 80, 73, 92, 36, 96, 37, 68, 2, 35, 83, 90, 25, 13, 24, 34, 42, 45, 74, 67, 16, 84, 97, 19, 64, 27, 14, 31, 12, 54, 60, 3, 8, 17, 89, 81, 94, 7, 29], [1, 18, 25, 13, 57, 53, 92, 95, 94, 88, 10, 82, 34, 83, 7, 28, 55, 11, 5, 58, 8, 9, 74, 99, 52, 32, 62, 45, 65, 50, 41, 56, 96, 44, 38, 47, 3, 39, 81, 19, 2, 22, 49, 12, 40, 67, 89, 76, 64, 70, 61, 21, 31, 54, 51, 17, 46, 30, 24, 60, 66, 26, 77, 63, 37, 35, 23, 6, 4, 87, 79, 97, 20, 48, 36, 85, 73, 71, 27, 43, 0, 15, 69, 78, 59, 86, 75, 33, 42, 84, 91, 93, 68, 80, 16, 98, 90, 72, 14, 29], [30, 16, 10, 67, 83, 81, 42, 94, 35, 59, 22, 5, 53, 61, 1, 96, 68, 45, 95, 66, 36, 37, 97, 87, 77, 93, 86, 33, 49, 13, 43, 14, 0, 34, 7, 2, 41, 21, 31, 32, 76, 55, 62, 72, 90, 71, 38, 23, 46, 12, 51, 19, 6, 44, 52, 48, 73, 24, 29, 74, 85, 99, 80, 28, 47, 9, 39, 84, 64, 57, 75, 98, 88, 26, 17, 63, 27, 56, 69, 8, 54, 25, 91, 78, 3, 50, 65, 70, 11, 4, 92, 60, 40, 58, 15, 89, 82, 18, 79, 20], [60, 88, 79, 35, 40, 43, 52, 4, 17, 31, 84, 44, 50, 94, 91, 38, 87, 25, 92, 62, 14, 97, 37, 18, 86, 28, 65, 90, 19, 29, 30, 75, 68, 49, 69, 11, 59, 41, 89, 33, 47, 54, 98, 42, 80, 56, 78, 99, 23, 82, 9, 48, 21, 1, 63, 22, 58, 95, 10, 12, 26, 74, 85, 13, 8, 27, 24, 53, 61, 34, 64, 71, 66, 32, 83, 73, 15, 67, 0, 20, 16, 6, 77, 45, 5, 93, 76, 39, 57, 2, 96, 46, 51, 3, 55, 7, 81, 70, 36, 72], [35, 56, 77, 58, 23, 83, 91, 81, 53, 70, 20, 74, 84, 50, 79, 51, 88, 44, 45, 71, 37, 26, 54, 48, 27, 43, 0, 12, 95, 97, 1, 63, 67, 98, 59, 40, 13, 19, 31, 87, 99, 16, 57, 30, 17, 92, 55, 68, 5, 46, 64, 8, 7, 42, 90, 33, 29, 9, 85, 24, 2, 69, 32, 10, 21, 65, 39, 86, 52, 62, 76, 89, 82, 6, 78, 4, 47, 28, 3, 75, 41, 15, 18, 14, 66, 73, 38, 80, 61, 49, 11, 22, 34, 93, 36, 25, 94, 96, 60, 72], [6, 90, 16, 43, 20, 55, 94, 8, 62, 59, 47, 32, 81, 67, 42, 35, 71, 19, 54, 49, 2, 88, 38, 5, 53, 77, 85, 11, 73, 34, 3, 72, 95, 58, 82, 64, 44, 29, 93, 14, 56, 98, 4, 37, 45, 75, 86, 60, 87, 7, 31, 17, 89, 97, 10, 70, 36, 99, 46, 63, 76, 41, 48, 84, 9, 52, 1, 24, 83, 25, 68, 18, 50, 26, 30, 27, 61, 0, 91, 33, 51, 40, 79, 39, 15, 74, 28, 78, 69, 96, 57, 65, 21, 80, 22, 23, 12, 13, 92, 66]], [[93, 42, 18, 65, 28, 87, 39, 35, 71, 23, 96, 90, 15, 58, 78, 33, 92, 88, 49, 64, 24, 84, 77, 8, 97, 50, 4, 53, 27, 83, 95, 31, 80, 47, 86, 55, 11, 40, 37, 14, 34, 60, 54, 12, 94, 9, 41, 2, 26, 10, 6, 57, 75, 63, 32, 43, 13, 52, 82, 73, 20, 30, 17, 5, 3, 68, 51, 89, 62, 79, 69, 70, 66, 45, 25, 22, 85, 0, 91, 76, 38, 7, 99, 61, 29, 98, 16, 36, 44, 67, 59, 56, 48, 81, 21, 46, 74, 72, 19, 1], [78, 91, 97, 77, 75, 85, 32, 2, 40, 86, 38, 18, 56, 47, 50, 87, 27, 92, 64, 39, 98, 23, 33, 72, 84, 58, 16, 99, 19, 65, 55, 73, 74, 42, 4, 48, 95, 8, 51, 3, 37, 82, 96, 69, 14, 44, 12, 21, 76, 70, 36, 15, 71, 41, 20, 31, 54, 13, 0, 9, 94, 67, 1, 60, 81, 61, 11, 6, 90, 5, 49, 10, 34, 7, 35, 30, 25, 88, 79, 93, 66, 62, 22, 24, 52, 17, 89, 45, 83, 57, 28, 46, 63, 68, 26, 29, 80, 59, 43, 53], [78, 91, 97, 77, 75, 85, 32, 2, 40, 86, 38, 18, 56, 47, 50, 87, 27, 92, 64, 39, 98, 23, 33, 72, 84, 58, 16, 99, 19, 65, 55, 73, 74, 42, 4, 48, 95, 8, 51, 3, 37, 82, 96, 69, 14, 44, 12, 21, 76, 70, 36, 15, 71, 41, 20, 31, 54, 13, 0, 9, 94, 67, 1, 60, 81, 61, 11, 6, 90, 5, 49, 10, 34, 7, 35, 30, 25, 88, 79, 93, 66, 62, 22, 24, 52, 17, 89, 45, 83, 57, 28, 46, 63, 68, 26, 29, 80, 59, 43, 53], [41, 65, 16, 86, 77, 67, 51, 81, 50, 25, 90, 87, 98, 99, 23, 9, 4, 97, 39, 36, 26, 42, 13, 66, 82, 22, 47, 88, 49, 46, 59, 78, 20, 19, 7, 93, 56, 84, 40, 61, 89, 21, 74, 1, 54, 44, 34, 6, 28, 8, 43, 76, 48, 71, 85, 38, 83, 18, 24, 79, 68, 80, 45, 33, 91, 27, 32, 70, 95, 3, 58, 60, 73, 10, 75, 52, 64, 2, 94, 30, 17, 55, 62, 35, 11, 12, 53, 63, 14, 31, 57, 0, 37, 72, 92, 15, 5, 29, 69, 96], [74, 50, 44, 80, 11, 46, 39, 54, 24, 3, 7, 62, 41, 8, 75, 23, 57, 82, 51, 86, 97, 79, 22, 60, 42, 14, 28, 67, 32, 73, 48, 56, 89, 26, 25, 77, 21, 68, 10, 2, 58, 76, 92, 95, 38, 29, 43, 35, 12, 16, 55, 17, 63, 91, 45, 64, 59, 13, 47, 31, 83, 5, 99, 49, 78, 71, 96, 53, 36, 90, 1, 66, 15, 0, 85, 65, 27, 4, 98, 94, 6, 84, 72, 30, 70, 20, 61, 69, 37, 93, 34, 87, 9, 52, 88, 81, 33, 19, 40, 18], [35, 67, 27, 53, 26, 79, 20, 46, 38, 4, 72, 84, 70, 58, 65, 91, 92, 21, 32, 71, 54, 24, 89, 0, 37, 8, 22, 81, 12, 87, 43, 18, 82, 17, 33, 76, 25, 13, 74, 51, 99, 3, 55, 60, 19, 73, 86, 62, 93, 52, 31, 64, 96, 66, 14, 40, 42, 69, 45, 6, 61, 34, 41, 59, 49, 10, 39, 2, 75, 80, 15, 94, 7, 23, 95, 78, 90, 5, 1, 28, 56, 30, 9, 98, 44, 48, 68, 77, 47, 11, 63, 83, 88, 36, 97, 29, 57, 50, 16, 85], [8, 51, 32, 96, 34, 24, 88, 54, 87, 83, 45, 99, 49, 30, 55, 61, 95, 60, 59, 76, 57, 5, 19, 56, 89, 66, 27, 94, 14, 6, 21, 58, 43, 74, 10, 2, 17, 62, 47, 16, 69, 84, 63, 39, 4, 92, 35, 48, 53, 64, 71, 50, 72, 28, 42, 46, 91, 23, 15, 40, 11, 78, 29, 86, 13, 90, 85, 20, 65, 93, 73, 80, 41, 37, 82, 79, 52, 9, 97, 38, 75, 25, 44, 7, 26, 12, 22, 0, 33, 1, 31, 68, 70, 67, 98, 18, 77, 36, 3, 81], [34, 17, 91, 45, 63, 64, 1, 71, 98, 78, 94, 3, 99, 12, 15, 93, 69, 19, 61, 80, 92, 81, 33, 51, 40, 10, 75, 24, 5, 87, 73, 46, 52, 86, 4, 70, 89, 56, 2, 67, 72, 58, 49, 84, 29, 18, 22, 38, 95, 36, 43, 35, 37, 85, 57, 8, 76, 7, 27, 28, 55, 74, 42, 13, 77, 31, 60, 39, 48, 68, 97, 79, 44, 54, 88, 82, 21, 66, 9, 23, 59, 50, 47, 16, 83, 25, 6, 30, 41, 96, 90, 14, 62, 20, 65, 11, 26, 32, 53, 0], [7, 51, 77, 80, 0, 53, 56, 27, 2, 78, 28, 32, 26, 22, 73, 93, 36, 54, 64, 99, 60, 50, 21, 11, 39, 42, 81, 8, 1, 79, 61, 5, 15, 31, 59, 33, 20, 94, 23, 88, 69, 17, 35, 95, 40, 75, 85, 87, 43, 47, 89, 12, 71, 72, 9, 83, 67, 38, 90, 82, 29, 10, 37, 91, 97, 74, 6, 86, 30, 63, 24, 49, 3, 13, 4, 57, 76, 70, 98, 34, 58, 52, 96, 84, 25, 55, 44, 46, 18, 65, 62, 68, 48, 66, 41, 19, 14, 45, 16, 92], [96, 2, 76, 15, 31, 22, 71, 38, 88, 26, 67, 0, 21, 10, 58, 39, 63, 77, 23, 50, 48, 19, 78, 30, 93, 91, 14, 12, 28, 11, 53, 73, 60, 61, 35, 79, 57, 70, 40, 20, 56, 32, 65, 64, 68, 55, 82, 94, 45, 95, 66, 7, 43, 16, 37, 99, 72, 62, 13, 4, 47, 8, 98, 89, 46, 29, 51, 85, 74, 17, 97, 84, 33, 18, 25, 83, 69, 44, 87, 49, 92, 9, 90, 36, 41, 81, 59, 54, 34, 6, 42, 5, 80, 3, 1, 86, 27, 52, 24, 75]], [[61, 85, 41, 37, 12, 25, 27, 17, 92, 52, 44, 66, 13, 15, 19, 78, 77, 9, 40, 20, 58, 43, 76, 24, 59, 42, 28, 30, 96, 86, 62, 89, 67, 35, 45, 6, 36, 50, 74, 26, 84, 95, 7, 68, 97, 79, 51, 16, 80, 3, 82, 2, 93, 21, 31, 98, 18, 60, 39, 72, 54, 65, 73, 32, 5, 70, 99, 10, 14, 71, 34, 4, 64, 33, 55, 48, 75, 87, 57, 81, 22, 46, 69, 63, 90, 23, 38, 56, 8, 29, 83, 88, 11, 0, 47, 53, 91, 94, 49, 1], [35, 22, 67, 24, 94, 82, 12, 68, 30, 43, 58, 96, 27, 69, 65, 18, 7, 79, 14, 2, 44, 60, 54, 47, 51, 83, 89, 3, 20, 11, 40, 85, 37, 48, 49, 8, 73, 15, 90, 93, 70, 84, 34, 4, 86, 98, 17, 46, 72, 63, 26, 56, 97, 74, 91, 99, 36, 80, 81, 41, 53, 88, 77, 21, 0, 23, 64, 76, 95, 33, 62, 1, 75, 87, 10, 66, 57, 6, 28, 25, 42, 9, 50, 39, 29, 78, 13, 19, 31, 45, 55, 61, 38, 71, 59, 5, 92, 52, 32, 16], [70, 29, 50, 57, 31, 9, 59, 45, 87, 71, 98, 89, 77, 97, 86, 5, 21, 61, 47, 41, 76, 37, 65, 12, 58, 75, 78, 91, 27, 63, 64, 83, 55, 95, 4, 11, 82, 23, 39, 40, 42, 68, 69, 48, 54, 13, 99, 33, 26, 0, 66, 79, 46, 72, 49, 44, 25, 74, 73, 28, 38, 10, 2, 85, 15, 19, 52, 94, 7, 36, 17, 32, 96, 3, 20, 30, 92, 51, 14, 90, 24, 67, 43, 34, 93, 84, 62, 81, 1, 56, 53, 88, 80, 35, 22, 6, 18, 16, 8, 60], [62, 75, 38, 50, 52, 86, 53, 73, 99, 59, 26, 46, 48, 90, 64, 1, 65, 13, 30, 36, 57, 16, 97, 91, 51, 33, 80, 67, 5, 25, 8, 96, 94, 84, 6, 89, 88, 20, 10, 85, 41, 56, 9, 34, 63, 0, 18, 12, 42, 15, 87, 4, 61, 43, 82, 17, 98, 60, 92, 70, 49, 71, 47, 54, 79, 83, 27, 74, 58, 2, 76, 93, 22, 69, 78, 44, 28, 95, 72, 68, 7, 55, 29, 77, 14, 23, 31, 32, 3, 37, 11, 66, 35, 39, 24, 81, 19, 21, 40, 45], [65, 78, 7, 83, 80, 77, 71, 72, 22, 85, 63, 73, 44, 87, 86, 88, 41, 30, 95, 67, 58, 21, 4, 5, 26, 27, 75, 31, 99, 52, 92, 64, 28, 8, 19, 98, 84, 34, 9, 48, 60, 0, 56, 1, 62, 16, 91, 32, 89, 79, 40, 11, 54, 51, 43, 12, 45, 66, 23, 13, 96, 81, 47, 36, 46, 93, 2, 69, 33, 3, 20, 6, 35, 18, 74, 68, 53, 37, 29, 61, 90, 57, 14, 42, 24, 76, 10, 38, 97, 39, 25, 50, 49, 70, 55, 82, 15, 17, 59, 94], [11, 17, 21, 48, 63, 0, 73, 14, 10, 88, 2, 28, 6, 9, 19, 69, 81, 13, 35, 95, 60, 56, 30, 47, 91, 92, 86, 29, 76, 50, 16, 25, 82, 93, 8, 5, 58, 94, 98, 20, 74, 77, 4, 52, 97, 79, 27, 42, 36, 12, 26, 72, 71, 45, 24, 87, 1, 39, 22, 89, 53, 31, 61, 37, 33, 18, 59, 43, 80, 15, 54, 38, 78, 90, 32, 83, 23, 44, 55, 66, 64, 3, 67, 49, 84, 62, 51, 41, 46, 85, 96, 34, 99, 75, 7, 40, 70, 68, 65, 57], [43, 38, 48, 47, 74, 88, 64, 54, 59, 35, 29, 18, 53, 91, 68, 66, 12, 79, 55, 41, 34, 36, 33, 94, 56, 87, 25, 6, 1, 8, 63, 96, 93, 44, 40, 65, 13, 77, 61, 85, 99, 80, 11, 51, 14, 46, 5, 39, 92, 27, 75, 52, 72, 83, 19, 62, 32, 24, 82, 95, 17, 37, 0, 15, 97, 4, 42, 86, 84, 3, 26, 81, 98, 9, 73, 22, 28, 78, 60, 76, 16, 23, 71, 89, 31, 57, 58, 20, 50, 10, 49, 45, 21, 67, 90, 30, 7, 2, 70, 69], [78, 35, 94, 59, 8, 23, 10, 76, 96, 80, 93, 9, 27, 95, 61, 84, 88, 91, 2, 33, 1, 85, 3, 36, 79, 18, 92, 5, 34, 81, 98, 40, 38, 68, 90, 70, 89, 65, 48, 6, 77, 30, 72, 62, 16, 83, 32, 54, 99, 82, 75, 41, 53, 17, 67, 43, 28, 21, 46, 7, 25, 64, 13, 14, 87, 58, 63, 31, 39, 47, 24, 71, 74, 55, 20, 11, 22, 45, 44, 51, 37, 15, 42, 56, 66, 29, 86, 49, 69, 57, 73, 50, 60, 0, 4, 19, 52, 97, 12, 26], [88, 86, 41, 1, 70, 10, 19, 2, 11, 44, 87, 26, 53, 59, 40, 18, 61, 13, 21, 56, 85, 75, 25, 5, 97, 7, 36, 67, 76, 79, 90, 65, 91, 0, 98, 89, 20, 55, 93, 58, 28, 63, 6, 83, 47, 71, 73, 49, 39, 31, 48, 69, 82, 50, 78, 62, 14, 74, 29, 54, 57, 80, 32, 94, 3, 66, 30, 35, 8, 46, 16, 51, 24, 17, 4, 84, 45, 60, 34, 15, 72, 77, 42, 12, 64, 9, 33, 95, 81, 96, 38, 43, 52, 99, 22, 92, 27, 23, 37, 68], [90, 93, 83, 21, 96, 71, 67, 28, 37, 75, 55, 58, 56, 39, 16, 46, 91, 41, 77, 92, 99, 65, 27, 5, 24, 1, 69, 7, 31, 35, 33, 64, 12, 14, 45, 11, 98, 0, 57, 72, 74, 13, 61, 40, 63, 89, 53, 85, 18, 76, 2, 70, 20, 60, 84, 52, 25, 43, 54, 17, 36, 19, 97, 73, 94, 62, 3, 23, 34, 88, 29, 80, 50, 22, 81, 87, 6, 30, 78, 48, 79, 44, 66, 8, 51, 86, 4, 15, 42, 10, 82, 32, 68, 26, 38, 47, 49, 9, 95, 59]]]; +var ibtable2 = [[4, 7, 8, 0, 9, 1, 3, 6, 2, 5], [5, 0, 4, 1, 3, 8, 9, 7, 6, 2], [0, 2, 7, 8, 9, 1, 6, 3, 5, 4], [5, 9, 8, 4, 1, 7, 0, 2, 3, 6], [7, 3, 0, 1, 8, 9, 6, 5, 2, 4], [7, 2, 4, 0, 1, 9, 6, 3, 5, 8], [4, 1, 6, 3, 5, 8, 0, 7, 2, 9], [6, 8, 4, 1, 5, 3, 7, 2, 9, 0], [4, 1, 8, 3, 7, 2, 0, 6, 5, 9], [7, 4, 5, 6, 2, 3, 9, 1, 8, 0]]; +function crc16(data, bits, initial = 65535, poly = 33800) { + let v = bigInt(initial); + let bigPoly = bigInt(poly); + for (let i = 0; i < bits; i++) { + v = v.shiftRight(1).xor(bigPoly.and(v.xor(data).and(bigInt.one).equals(bigInt.one) ? bigPoly : bigInt.zero)); + data = data.shiftRight(1); + } + return v.toJSNumber(); +} +function decodeAccessCode(code) { + code = code.replace(/\D/i, ""); + if (code.length !== 20) { + return null; + } + let body = _.range(3, 15, 2).map((i) => parseInt(code[i]) * 10 + parseInt(code[i + 1])); + let crc = _.range(15, 20).map((i) => parseInt(code[i])); + let boxes = [(crc[3] + crc[2]) % 10, crc[2], crc[3], crc[4], (crc[4] + crc[0]) % 10, crc[1]]; + for (const [n, i] of body.entries()) { + body[n] = ibtable[4][boxes[n]][i]; + } + const rv = body[0] >> 4; + boxes = [(crc[1] + crc[0]) % 10, crc[1], crc[2], crc[3], crc[4], (crc[4] + crc[1]) % 10]; + for (const [n, i] of body.entries()) { + if (n == 0) { + body[n] = body[n] & 240 | ibtable2[boxes[n]][body[n] & 15]; + } else { + body[n] = ibtable[rv][boxes[n]][i]; + } + } + const serial = body.map((i) => i.toString().padStart(2, "0")).join(""); + if (crc16(bigInt(code.substring(0, 3) + serial, 16), 15 * 4) !== parseInt(code.substring(15, 20))) { + throw new Error(`CRC16 mismatch.`); + } + return { revision: rv, serial: parseInt(serial) }; +} +function encodeAccessCode(company, serial, rev = 0) { + if (company < 0 || company > 999) { + throw new Error(`Invalid company code`); + } + if (serial < 0 || serial > 99999999999) { + throw new Error(`Invalid serial number`); + } + if (rev < 0 || rev > sbtable.length) { + throw new Error(`Invalid revision`); + } + const bodyStr = `${rev}${serial.toString().padStart(11, "0")}`; + const crc_i = crc16(bigInt(company.toString().padStart(3, "0") + bodyStr, 16), 15 * 4); + const crc = _.range(5).map((i) => Math.floor(crc_i / 10 ** (4 - i)) % 10); + const body = _.range(0, 12, 2).map((i) => parseInt(bodyStr[i]) * 10 + parseInt(bodyStr[i + 1])); + let boxes = [(crc[1] + crc[0]) % 10, crc[1], crc[2], crc[3], crc[4], (crc[4] + crc[1]) % 10]; + for (const [n, i] of body.entries()) { + if (n == 0) { + body[n] = body[n] & 240 | sbtable2[boxes[n]][body[n] & 15]; + } else { + body[n] = sbtable[rev][boxes[n]][i]; + } + } + boxes = [(crc[3] + crc[2]) % 10, crc[2], crc[3], crc[4], (crc[4] + crc[0]) % 10, crc[1]]; + for (const [n, i] of body.entries()) { + body[n] = sbtable[4][boxes[n]][i]; + } + return `${company.toString().padStart(3, "0")}${body.map((i) => i.toString().padStart(2, "0")).join("")}${crc_i.toString().padStart(5, "0")}`; } // src/card.ts var CARD_ID_REGEX = /^(?:[0-9]{4} ?){5}$/i; +var AMNET_COMPANY_ID = 597; function generateCardNumber() { - let cardId = ""; - while (true) { - const firstDigit = Math.floor(Math.random() * 10); - if (firstDigit !== 3) { - cardId = firstDigit.toString(); - break; - } - } - for (let i = 0; i < 19; i++) { - cardId += Math.floor(Math.random() * 10).toString(); - } - return cardId; + const serial = Math.floor(Math.random() * 1e11); + return encodeAccessCode(AMNET_COMPANY_ID, serial, 0); } function validateCardId(id) { return id[0] !== "3" && CARD_ID_REGEX.test(id); @@ -119,7 +157,10 @@ function getGameName(id) { } export { AMNET_API_VERSION, + AMNET_COMPANY_ID, CARD_ID_REGEX, + decodeAccessCode as DecodeAMAccessCode, + encodeAccessCode as EncodeAMAccessCode, MIN_AMNET_API_VERSION, fetchServerInfo, generateCardNumber, diff --git a/amnet-shared/dist/index.mjs.map b/amnet-shared/dist/index.mjs.map index be11df6..68c17b7 100644 --- a/amnet-shared/dist/index.mjs.map +++ b/amnet-shared/dist/index.mjs.map @@ -1 +1 @@ -{"version":3,"sources":["../src/api.ts","../src/card.ts","../src/gameIds.ts"],"sourcesContent":["/**\n * The latest version of the AMNet API this library supports\n */\nexport const AMNET_API_VERSION = 1;\n\n/**\n * The minimum version of the AMNet API this library supports\n */\nexport const MIN_AMNET_API_VERSION = 1;\n\nexport interface AMCardInRequest {\n cardId: string;\n}\n\n/**\n * Server connection info (api version, address, etc.)\n */\nexport interface AMServerConnectionInfo {\n apiVersion: number;\n serverAddress: string;\n}\n\n/**\n * User-definable server metadata\n */\nexport interface AMServerMetadata {\n serverName: string;\n gameId?: string | null | undefined;\n}\n\n/**\n * Metrics about the current game session\n */\nexport interface AMServerInstanceMetrics {\n timeSinceLastPoll?: number;\n sessionUptime?: number;\n}\n\n/**\n * The response from an AMNet server's info endpoint\n */\nexport type AMServerInfo = AMServerMetadata & AMServerConnectionInfo & AMServerInstanceMetrics;\n\n/**\n * Performs the card-in request to the specified server\n * @param server The server to perform the request against\n * @param request The card-in request to send\n * @param signal The abort signal to use for the request\n */\nexport async function performCardIn(server: AMServerConnectionInfo, request: AMCardInRequest, signal: AbortSignal): Promise {\n if (server.apiVersion < MIN_AMNET_API_VERSION || server.apiVersion > AMNET_API_VERSION) {\n throw new Error(\"Unsupported server API version\");\n }\n \n try {\n const response = await fetch(`${new URL(server.serverAddress).origin}/amnet/signin`, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\"\n },\n body: JSON.stringify(request),\n signal: signal\n });\n\n return response.ok;\n } catch {\n return false;\n }\n}\n\n/**\n * Attempts to connect to the specified server and fetch its info\n * @param serverAddress The origin address of the server to connect to\n * @param abort The abort signal to use for the request (for cancellation)\n */\nexport async function fetchServerInfo(serverAddress: string, abort: AbortSignal): Promise {\n try {\n const response = await fetch(`${new URL(serverAddress).origin}/amnet/info`, {\n signal: abort\n });\n \n if (!response.ok) {\n return null;\n }\n\n return {\n ...await response.json(),\n serverAddress: serverAddress\n } satisfies AMServerMetadata;\n } catch {\n return null;\n }\n}\n","export const CARD_ID_REGEX = /^(?:[0-9]{4} ?){5}$/i;\n\nexport function generateCardNumber(): string {\n let cardId = '';\n\n while (true) {\n // don't start with a 3\n const firstDigit = Math.floor(Math.random() * 10);\n\n if (firstDigit !== 3) {\n cardId = firstDigit.toString();\n break;\n }\n }\n\n for (let i = 0; i < 19; i++) {\n cardId += Math.floor(Math.random() * 10).toString();\n }\n\n return cardId;\n}\n\n/**\n * Validates the provided card id by known parameters\n * @param id The card id to validate\n */\nexport function validateCardId(id: string): boolean {\n return id[0] !== '3' && CARD_ID_REGEX.test(id);\n}\n","/**\n * Get the game name from the game identifier (4-letter code)\n * @param id\n */\nexport function getGameName(id: string): string | null {\n switch (id?.toUpperCase()) {\n case \"SDGT\":\n return \"Initial D The Arcade\";\n case \"SDHD\":\n case \"SDBT\":\n return \"CHUNITHM\";\n case \"SDDT\":\n return \"O.N.G.E.K.I.\";\n case \"SDEZ\":\n return \"maimai DX\";\n case \"SBZV\":\n return \"Project DIVA Future Tone\";\n \n default:\n return null;\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAGO,IAAM,oBAAoB;AAK1B,IAAM,wBAAwB;AAyCrC,SAAsB,cAAc,QAAgC,SAA0B,QAAuC;AAAA;AACjI,QAAI,OAAO,aAAa,yBAAyB,OAAO,aAAa,mBAAmB;AACpF,YAAM,IAAI,MAAM,gCAAgC;AAAA,IACpD;AAEA,QAAI;AACA,YAAM,WAAW,MAAM,MAAM,GAAG,IAAI,IAAI,OAAO,aAAa,EAAE,MAAM,iBAAiB;AAAA,QACjF,QAAQ;AAAA,QACR,SAAS;AAAA,UACL,gBAAgB;AAAA,QACpB;AAAA,QACA,MAAM,KAAK,UAAU,OAAO;AAAA,QAC5B;AAAA,MACJ,CAAC;AAED,aAAO,SAAS;AAAA,IACpB,SAAQ;AACJ,aAAO;AAAA,IACX;AAAA,EACJ;AAAA;AAOA,SAAsB,gBAAgB,eAAuB,OAAkD;AAAA;AAC3G,QAAI;AACA,YAAM,WAAW,MAAM,MAAM,GAAG,IAAI,IAAI,aAAa,EAAE,MAAM,eAAe;AAAA,QACxE,QAAQ;AAAA,MACZ,CAAC;AAED,UAAI,CAAC,SAAS,IAAI;AACd,eAAO;AAAA,MACX;AAEA,aAAO,iCACA,MAAM,SAAS,KAAK,IADpB;AAAA,QAEH;AAAA,MACJ;AAAA,IACJ,SAAQ;AACJ,aAAO;AAAA,IACX;AAAA,EACJ;AAAA;;;AC5FO,IAAM,gBAAgB;AAEtB,SAAS,qBAA6B;AACzC,MAAI,SAAS;AAEb,SAAO,MAAM;AAET,UAAM,aAAa,KAAK,MAAM,KAAK,OAAO,IAAI,EAAE;AAEhD,QAAI,eAAe,GAAG;AAClB,eAAS,WAAW,SAAS;AAC7B;AAAA,IACJ;AAAA,EACJ;AAEA,WAAS,IAAI,GAAG,IAAI,IAAI,KAAK;AACzB,cAAU,KAAK,MAAM,KAAK,OAAO,IAAI,EAAE,EAAE,SAAS;AAAA,EACtD;AAEA,SAAO;AACX;AAMO,SAAS,eAAe,IAAqB;AAChD,SAAO,GAAG,CAAC,MAAM,OAAO,cAAc,KAAK,EAAE;AACjD;;;ACxBO,SAAS,YAAY,IAA2B;AACnD,UAAQ,yBAAI,eAAe;AAAA,IACvB,KAAK;AACD,aAAO;AAAA,IACX,KAAK;AAAA,IACL,KAAK;AACD,aAAO;AAAA,IACX,KAAK;AACD,aAAO;AAAA,IACX,KAAK;AACD,aAAO;AAAA,IACX,KAAK;AACD,aAAO;AAAA,IAEX;AACI,aAAO;AAAA,EACf;AACJ;","names":[]} \ No newline at end of file +{"version":3,"sources":["../src/api.ts","../src/card-encoding.ts","../src/card.ts","../src/gameIds.ts"],"sourcesContent":["/**\n * The latest version of the AMNet API this library supports\n */\nexport const AMNET_API_VERSION = 1;\n\n/**\n * The minimum version of the AMNet API this library supports\n */\nexport const MIN_AMNET_API_VERSION = 1;\n\nexport interface AMCardInRequest {\n cardId: string;\n physicalCardIDm?: string;\n}\n\n/**\n * Server connection info (api version, address, etc.)\n */\nexport interface AMServerConnectionInfo {\n apiVersion: number;\n serverAddress: string;\n}\n\n/**\n * User-definable server metadata\n */\nexport interface AMServerMetadata {\n serverName: string;\n gameId?: string | null | undefined;\n}\n\n/**\n * Metrics about the current game session\n */\nexport interface AMServerInstanceMetrics {\n timeSinceLastPoll?: number;\n sessionUptime?: number;\n}\n\n/**\n * The response from an AMNet server's info endpoint\n */\nexport type AMServerInfo = AMServerMetadata & AMServerConnectionInfo & AMServerInstanceMetrics;\n\n/**\n * Performs the card-in request to the specified server\n * @param server The server to perform the request against\n * @param request The card-in request to send\n * @param signal The abort signal to use for the request\n */\nexport async function performCardIn(server: AMServerConnectionInfo, request: AMCardInRequest, signal: AbortSignal): Promise {\n if (server.apiVersion < MIN_AMNET_API_VERSION || server.apiVersion > AMNET_API_VERSION) {\n throw new Error(\"Unsupported server API version\");\n }\n\n try {\n const response = await fetch(`${new URL(server.serverAddress).origin}/amnet/signin`, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\"\n },\n body: JSON.stringify(request),\n signal: signal\n });\n\n return response.ok;\n } catch {\n return false;\n }\n}\n\n/**\n * Attempts to connect to the specified server and fetch its info\n * @param serverAddress The origin address of the server to connect to\n * @param abort The abort signal to use for the request (for cancellation)\n */\nexport async function fetchServerInfo(serverAddress: string, abort: AbortSignal): Promise {\n try {\n const response = await fetch(`${new URL(serverAddress).origin}/amnet/info`, {\n signal: abort\n });\n\n if (!response.ok) {\n return null;\n }\n\n return {\n ...await response.json(),\n serverAddress: serverAddress\n } satisfies AMServerMetadata;\n } catch {\n return null;\n }\n}\n","import _ from \"lodash\";\nimport bigInt, {BigInteger} from \"big-integer\";\n\nconst sbtable = [[[45, 50, 94, 2, 66, 55, 56, 49, 99, 36, 60, 0, 73, 30, 39, 37, 80, 74, 85, 7, 12, 33, 93, 83, 95, 91, 98, 92, 23, 24, 79, 21, 31, 35, 71, 70, 4, 43, 1, 5, 88, 90, 69, 58, 76, 20, 84, 62, 77, 44, 61, 11, 16, 53, 82, 34, 13, 47, 48, 87, 89, 15, 64, 3, 54, 28, 57, 67, 9, 75, 32, 65, 96, 17, 18, 29, 10, 14, 42, 6, 46, 26, 40, 59, 63, 78, 68, 8, 86, 51, 25, 72, 38, 97, 19, 81, 27, 41, 52, 22], [26, 32, 34, 79, 42, 45, 4, 75, 22, 73, 64, 98, 49, 19, 5, 24, 6, 55, 63, 25, 40, 77, 54, 12, 9, 44, 83, 71, 0, 90, 97, 96, 81, 80, 3, 31, 56, 92, 17, 86, 72, 28, 36, 78, 62, 30, 7, 46, 87, 20, 82, 50, 35, 61, 41, 94, 68, 11, 1, 10, 74, 67, 85, 43, 57, 15, 95, 84, 65, 53, 69, 52, 76, 88, 2, 14, 37, 58, 93, 16, 59, 51, 18, 99, 39, 47, 89, 8, 13, 91, 38, 33, 70, 48, 23, 29, 27, 66, 60, 21], [28, 53, 30, 85, 0, 95, 70, 47, 40, 51, 94, 68, 99, 15, 5, 57, 1, 16, 80, 93, 91, 52, 2, 32, 48, 77, 41, 75, 22, 39, 50, 81, 79, 73, 97, 76, 60, 4, 59, 25, 78, 38, 46, 58, 90, 84, 56, 6, 83, 62, 42, 10, 64, 31, 36, 61, 65, 63, 18, 8, 9, 96, 55, 26, 89, 67, 3, 98, 35, 21, 13, 12, 88, 71, 37, 29, 87, 49, 24, 86, 92, 20, 44, 74, 69, 17, 82, 54, 27, 7, 23, 66, 11, 19, 34, 45, 14, 72, 43, 33], [32, 44, 86, 79, 38, 61, 25, 8, 5, 85, 78, 48, 33, 87, 84, 35, 64, 41, 60, 21, 96, 75, 6, 69, 39, 94, 3, 92, 37, 77, 15, 13, 29, 59, 76, 91, 65, 56, 73, 83, 27, 62, 89, 50, 18, 98, 81, 17, 71, 28, 82, 11, 30, 43, 34, 20, 70, 22, 46, 63, 52, 68, 90, 53, 36, 10, 74, 58, 40, 88, 9, 2, 42, 26, 24, 4, 95, 57, 31, 66, 0, 14, 49, 16, 99, 19, 51, 23, 47, 12, 93, 1, 7, 80, 45, 97, 55, 67, 72, 54], [58, 35, 42, 38, 63, 36, 68, 30, 81, 4, 87, 80, 32, 69, 37, 67, 1, 86, 61, 94, 27, 11, 84, 26, 59, 73, 53, 66, 72, 71, 39, 33, 99, 8, 43, 88, 17, 22, 89, 5, 46, 93, 98, 48, 55, 83, 34, 3, 0, 16, 12, 20, 78, 9, 2, 76, 54, 51, 25, 24, 62, 57, 92, 10, 50, 28, 79, 23, 52, 95, 44, 60, 74, 90, 19, 77, 21, 31, 96, 49, 64, 6, 29, 85, 18, 13, 82, 47, 56, 45, 15, 7, 97, 75, 40, 41, 65, 14, 70, 91], [81, 82, 66, 72, 83, 4, 20, 94, 53, 48, 77, 41, 67, 64, 9, 24, 36, 55, 14, 1, 78, 84, 49, 0, 44, 58, 70, 25, 28, 73, 8, 68, 88, 54, 86, 87, 23, 52, 27, 5, 97, 37, 62, 50, 3, 89, 92, 47, 30, 10, 29, 80, 22, 26, 11, 13, 69, 60, 38, 90, 85, 57, 12, 75, 46, 39, 74, 33, 42, 93, 98, 91, 59, 99, 18, 6, 17, 16, 32, 40, 63, 7, 76, 15, 43, 71, 51, 35, 2, 65, 34, 96, 19, 56, 79, 21, 95, 45, 61, 31], [25, 88, 7, 57, 98, 63, 86, 13, 69, 84, 56, 20, 68, 90, 35, 6, 43, 93, 95, 3, 75, 4, 9, 28, 31, 66, 21, 44, 30, 76, 11, 22, 49, 2, 77, 40, 85, 19, 82, 16, 97, 92, 39, 96, 18, 32, 42, 94, 70, 71, 54, 79, 67, 78, 37, 12, 99, 53, 61, 41, 87, 17, 1, 14, 52, 10, 47, 58, 27, 46, 36, 55, 26, 15, 33, 50, 72, 51, 89, 23, 74, 59, 64, 8, 83, 65, 80, 29, 38, 0, 60, 24, 45, 81, 48, 91, 73, 5, 34, 62], [73, 85, 37, 11, 80, 46, 16, 47, 88, 65, 94, 64, 12, 38, 98, 70, 95, 48, 92, 18, 56, 75, 58, 7, 81, 15, 74, 13, 5, 44, 27, 32, 76, 90, 33, 55, 26, 96, 77, 24, 0, 89, 8, 4, 28, 39, 71, 3, 10, 41, 91, 53, 31, 68, 36, 17, 69, 60, 34, 54, 93, 82, 21, 51, 87, 59, 61, 6, 1, 23, 30, 66, 43, 25, 35, 42, 49, 78, 62, 14, 19, 20, 29, 22, 52, 83, 63, 45, 2, 99, 50, 79, 72, 40, 84, 97, 86, 57, 67, 9], [48, 94, 17, 55, 59, 24, 72, 75, 38, 85, 34, 98, 95, 36, 49, 63, 57, 54, 29, 6, 52, 47, 73, 1, 82, 9, 66, 83, 31, 61, 78, 60, 97, 14, 87, 15, 90, 70, 53, 10, 27, 8, 3, 64, 51, 50, 68, 26, 22, 19, 42, 96, 67, 7, 25, 39, 92, 30, 58, 93, 21, 74, 41, 18, 65, 44, 88, 32, 71, 69, 12, 77, 13, 11, 99, 79, 37, 89, 81, 35, 86, 56, 45, 76, 46, 80, 62, 43, 16, 84, 40, 5, 33, 91, 4, 20, 0, 23, 28, 2], [61, 45, 79, 13, 59, 52, 6, 77, 3, 31, 70, 80, 26, 33, 36, 4, 27, 32, 24, 74, 29, 94, 16, 12, 76, 7, 88, 57, 78, 42, 97, 96, 43, 83, 92, 21, 51, 47, 49, 58, 90, 41, 93, 98, 35, 63, 86, 37, 5, 30, 28, 72, 25, 22, 60, 19, 39, 34, 68, 50, 8, 64, 46, 99, 84, 87, 69, 56, 53, 55, 44, 54, 89, 65, 85, 0, 71, 15, 17, 66, 81, 82, 91, 95, 62, 48, 38, 75, 40, 14, 9, 10, 73, 67, 18, 11, 23, 2, 20, 1]], [[95, 90, 61, 38, 18, 7, 83, 39, 79, 14, 48, 21, 81, 44, 78, 50, 56, 91, 12, 86, 99, 98, 43, 63, 73, 87, 42, 72, 15, 68, 97, 23, 88, 69, 2, 51, 19, 58, 59, 22, 20, 29, 82, 11, 75, 70, 9, 71, 27, 30, 47, 89, 92, 60, 46, 76, 93, 54, 1, 96, 94, 57, 40, 62, 41, 3, 28, 64, 37, 74, 67, 16, 65, 53, 5, 36, 24, 45, 32, 33, 10, 85, 26, 4, 84, 77, 35, 13, 6, 8, 17, 80, 25, 55, 52, 66, 49, 34, 0, 31], [18, 14, 70, 43, 74, 45, 94, 36, 40, 6, 31, 46, 15, 47, 13, 19, 72, 61, 99, 21, 17, 92, 88, 78, 73, 90, 0, 96, 20, 28, 25, 51, 50, 77, 29, 16, 54, 12, 58, 38, 71, 23, 42, 83, 65, 60, 10, 33, 22, 76, 95, 32, 57, 5, 59, 67, 68, 3, 91, 85, 26, 62, 41, 1, 53, 82, 34, 24, 87, 27, 89, 75, 56, 30, 81, 7, 8, 4, 64, 66, 9, 63, 35, 52, 80, 93, 69, 84, 55, 86, 48, 98, 79, 97, 49, 44, 39, 11, 37, 2], [76, 16, 73, 29, 34, 14, 36, 90, 58, 70, 46, 2, 91, 59, 63, 32, 84, 40, 78, 38, 19, 37, 0, 31, 8, 44, 94, 39, 10, 66, 42, 1, 21, 88, 82, 97, 33, 4, 99, 74, 89, 62, 25, 87, 77, 43, 50, 95, 64, 23, 47, 93, 65, 27, 12, 71, 9, 72, 60, 18, 7, 22, 79, 24, 96, 45, 49, 98, 57, 11, 5, 86, 3, 80, 26, 51, 17, 85, 54, 67, 48, 35, 53, 41, 28, 13, 20, 92, 83, 69, 6, 68, 75, 52, 61, 30, 81, 56, 15, 55], [0, 62, 25, 61, 56, 87, 54, 27, 75, 49, 18, 69, 17, 71, 40, 6, 90, 80, 23, 26, 68, 24, 10, 21, 47, 88, 36, 55, 15, 22, 48, 12, 83, 99, 46, 67, 59, 29, 58, 73, 78, 97, 19, 33, 51, 98, 65, 91, 16, 4, 63, 41, 3, 70, 30, 8, 89, 34, 72, 60, 9, 95, 50, 2, 66, 53, 44, 85, 28, 5, 92, 43, 64, 96, 74, 77, 45, 52, 14, 42, 1, 32, 20, 76, 86, 82, 94, 7, 39, 13, 31, 11, 84, 93, 35, 37, 38, 57, 79, 81], [78, 8, 59, 25, 69, 15, 63, 3, 57, 5, 50, 96, 41, 66, 80, 81, 7, 45, 60, 74, 79, 32, 27, 58, 56, 82, 11, 47, 17, 85, 53, 40, 95, 84, 76, 92, 18, 71, 64, 51, 67, 91, 22, 34, 65, 31, 73, 93, 68, 75, 77, 37, 43, 12, 20, 99, 2, 1, 19, 35, 44, 55, 90, 9, 0, 6, 33, 89, 24, 14, 97, 10, 48, 61, 23, 54, 98, 86, 88, 94, 46, 70, 28, 36, 16, 30, 4, 39, 26, 38, 87, 52, 83, 49, 62, 42, 72, 29, 13, 21], [20, 88, 35, 5, 85, 98, 11, 78, 62, 83, 79, 80, 40, 14, 91, 8, 7, 69, 71, 61, 49, 38, 64, 82, 0, 47, 84, 95, 2, 50, 77, 41, 97, 36, 33, 81, 46, 21, 73, 48, 31, 92, 54, 89, 87, 60, 90, 10, 76, 45, 99, 52, 3, 44, 39, 43, 18, 16, 63, 12, 28, 70, 86, 6, 4, 24, 59, 30, 96, 65, 22, 56, 74, 23, 32, 75, 53, 93, 15, 67, 66, 17, 29, 25, 42, 37, 57, 9, 72, 68, 26, 34, 27, 51, 19, 58, 55, 94, 13, 1], [72, 53, 79, 61, 30, 33, 25, 75, 8, 55, 14, 6, 22, 93, 18, 77, 4, 74, 44, 36, 82, 94, 2, 5, 62, 54, 28, 3, 63, 97, 65, 7, 84, 73, 39, 92, 67, 91, 24, 45, 15, 81, 19, 78, 80, 64, 34, 43, 32, 87, 52, 95, 89, 37, 10, 23, 20, 68, 42, 47, 59, 58, 49, 71, 40, 85, 13, 31, 12, 57, 96, 90, 56, 41, 48, 9, 99, 35, 98, 26, 1, 46, 11, 69, 27, 83, 60, 50, 21, 70, 0, 88, 29, 86, 76, 16, 66, 38, 51, 17], [3, 68, 86, 94, 81, 90, 85, 32, 65, 52, 50, 42, 80, 78, 26, 93, 57, 58, 69, 82, 92, 27, 11, 67, 95, 41, 21, 88, 35, 17, 19, 15, 22, 62, 40, 76, 63, 59, 37, 55, 75, 9, 24, 89, 56, 53, 23, 60, 25, 6, 1, 71, 16, 7, 10, 44, 8, 12, 87, 64, 54, 72, 20, 33, 70, 79, 14, 97, 4, 99, 45, 39, 2, 77, 98, 74, 49, 30, 13, 61, 66, 73, 47, 43, 96, 83, 18, 91, 28, 48, 38, 34, 31, 36, 29, 0, 84, 46, 5, 51], [71, 84, 25, 70, 77, 56, 61, 47, 72, 27, 54, 89, 9, 46, 95, 59, 42, 98, 63, 69, 48, 16, 97, 14, 66, 83, 87, 68, 17, 2, 15, 79, 31, 1, 57, 12, 33, 36, 0, 40, 21, 50, 76, 41, 10, 13, 44, 5, 53, 4, 38, 35, 55, 96, 81, 91, 90, 64, 34, 51, 6, 28, 32, 39, 75, 18, 93, 24, 78, 7, 52, 43, 49, 37, 74, 8, 58, 65, 92, 67, 85, 20, 94, 88, 80, 86, 19, 60, 3, 11, 30, 45, 29, 22, 26, 73, 99, 23, 62, 82], [67, 91, 46, 33, 76, 3, 96, 23, 9, 68, 49, 63, 1, 92, 58, 62, 69, 77, 70, 75, 71, 94, 51, 55, 50, 52, 0, 88, 18, 16, 73, 6, 12, 87, 93, 79, 84, 57, 48, 41, 20, 47, 15, 42, 54, 81, 7, 30, 34, 56, 29, 8, 98, 5, 45, 64, 83, 74, 22, 82, 80, 95, 2, 72, 44, 31, 86, 78, 13, 10, 28, 89, 60, 35, 61, 19, 14, 85, 4, 43, 11, 40, 26, 99, 39, 32, 90, 17, 24, 37, 36, 21, 25, 53, 97, 59, 27, 38, 65, 66]], [[40, 77, 66, 65, 97, 96, 58, 64, 69, 30, 0, 3, 17, 33, 51, 23, 59, 10, 7, 20, 29, 49, 71, 13, 46, 4, 79, 92, 47, 18, 72, 57, 73, 80, 56, 28, 78, 67, 9, 87, 43, 31, 22, 62, 75, 99, 19, 63, 35, 93, 12, 98, 25, 26, 37, 89, 86, 15, 55, 50, 91, 38, 42, 81, 2, 94, 70, 68, 45, 88, 76, 74, 11, 24, 41, 60, 85, 21, 44, 32, 82, 61, 52, 83, 53, 36, 48, 1, 95, 27, 14, 84, 54, 6, 39, 34, 90, 5, 16, 8], [44, 69, 53, 28, 18, 11, 23, 65, 96, 25, 93, 42, 72, 58, 95, 56, 32, 21, 78, 77, 51, 34, 47, 7, 66, 13, 88, 67, 92, 98, 10, 50, 90, 45, 49, 9, 99, 94, 22, 24, 5, 85, 33, 3, 73, 35, 52, 63, 2, 76, 87, 43, 81, 83, 55, 61, 70, 75, 16, 14, 8, 71, 57, 40, 86, 39, 80, 79, 26, 48, 59, 4, 82, 0, 36, 12, 54, 38, 64, 17, 91, 27, 62, 84, 37, 74, 68, 1, 6, 19, 29, 46, 60, 30, 89, 15, 20, 97, 41, 31], [53, 22, 34, 16, 72, 71, 14, 94, 12, 59, 39, 6, 38, 68, 21, 93, 32, 46, 69, 55, 10, 8, 75, 60, 9, 13, 99, 90, 63, 49, 28, 92, 41, 7, 54, 83, 27, 91, 47, 43, 31, 74, 42, 40, 18, 81, 76, 84, 78, 52, 1, 26, 51, 2, 58, 11, 65, 67, 15, 23, 0, 79, 96, 4, 29, 62, 89, 66, 50, 98, 56, 61, 30, 88, 35, 25, 77, 70, 3, 44, 95, 80, 19, 64, 57, 37, 82, 85, 73, 48, 5, 86, 24, 36, 33, 97, 20, 45, 17, 87], [95, 36, 70, 82, 23, 55, 13, 51, 83, 38, 40, 18, 84, 74, 56, 85, 58, 14, 19, 69, 34, 59, 97, 89, 52, 77, 9, 91, 68, 16, 27, 88, 6, 73, 43, 5, 10, 66, 4, 61, 44, 46, 72, 50, 96, 21, 33, 15, 32, 0, 63, 92, 24, 39, 29, 49, 30, 64, 12, 26, 67, 53, 37, 2, 47, 65, 3, 20, 75, 78, 99, 87, 98, 1, 81, 90, 62, 54, 22, 35, 45, 25, 86, 48, 17, 60, 94, 8, 42, 31, 76, 28, 11, 57, 93, 41, 7, 71, 80, 79], [60, 24, 69, 92, 15, 36, 11, 98, 93, 27, 51, 35, 89, 74, 87, 4, 81, 94, 23, 84, 56, 3, 42, 18, 75, 73, 46, 86, 55, 99, 0, 88, 1, 26, 76, 70, 65, 67, 20, 13, 7, 45, 77, 17, 9, 78, 54, 48, 32, 40, 47, 31, 2, 6, 90, 10, 8, 50, 52, 38, 91, 14, 53, 12, 85, 44, 21, 80, 68, 33, 30, 57, 61, 63, 79, 41, 29, 39, 58, 5, 62, 96, 28, 71, 82, 34, 25, 43, 22, 95, 72, 37, 64, 16, 97, 59, 66, 83, 49, 19], [80, 0, 40, 36, 68, 18, 67, 14, 20, 21, 10, 17, 43, 3, 98, 81, 94, 55, 1, 39, 72, 51, 41, 66, 58, 2, 61, 78, 15, 99, 57, 52, 25, 87, 12, 65, 74, 64, 34, 37, 44, 30, 88, 79, 33, 27, 56, 35, 73, 42, 29, 54, 24, 5, 53, 16, 31, 4, 19, 84, 59, 50, 26, 63, 48, 28, 60, 45, 92, 82, 49, 77, 97, 76, 22, 86, 47, 62, 83, 70, 93, 38, 11, 13, 89, 75, 85, 69, 9, 46, 96, 90, 6, 91, 8, 7, 32, 71, 95, 23], [32, 14, 35, 84, 89, 11, 52, 34, 79, 65, 2, 88, 49, 29, 31, 94, 1, 74, 97, 51, 99, 37, 10, 47, 57, 81, 73, 76, 63, 58, 0, 38, 39, 27, 33, 8, 20, 21, 46, 66, 92, 36, 6, 30, 53, 17, 48, 64, 55, 28, 85, 50, 54, 12, 80, 41, 77, 69, 93, 9, 91, 13, 42, 75, 68, 86, 19, 3, 16, 78, 87, 45, 43, 56, 59, 70, 40, 24, 83, 98, 62, 5, 96, 4, 67, 60, 26, 23, 72, 95, 44, 82, 90, 25, 7, 18, 15, 22, 71, 61], [78, 53, 89, 93, 7, 84, 81, 95, 64, 50, 58, 35, 59, 63, 20, 76, 80, 8, 23, 28, 79, 52, 55, 48, 66, 17, 60, 65, 25, 29, 30, 9, 73, 39, 69, 3, 98, 22, 15, 87, 4, 37, 43, 5, 11, 83, 91, 40, 51, 33, 12, 92, 6, 67, 41, 94, 45, 88, 56, 36, 0, 68, 19, 54, 70, 26, 72, 77, 32, 34, 97, 71, 99, 75, 61, 31, 86, 82, 46, 2, 44, 96, 49, 74, 10, 62, 24, 16, 1, 38, 27, 14, 18, 85, 13, 57, 90, 21, 42, 47], [26, 30, 60, 78, 75, 48, 73, 52, 51, 57, 63, 90, 27, 36, 83, 81, 41, 44, 82, 37, 10, 64, 91, 4, 59, 95, 21, 24, 77, 56, 43, 38, 62, 55, 92, 0, 94, 20, 86, 66, 35, 80, 53, 25, 17, 18, 49, 76, 23, 89, 13, 15, 68, 8, 22, 46, 1, 42, 3, 34, 98, 88, 69, 31, 50, 65, 84, 32, 47, 61, 9, 19, 99, 85, 11, 79, 70, 2, 74, 14, 87, 7, 72, 5, 12, 58, 67, 39, 16, 71, 54, 6, 45, 93, 96, 28, 97, 29, 33, 40], [77, 66, 20, 30, 42, 23, 0, 49, 7, 64, 54, 27, 96, 97, 39, 84, 2, 51, 71, 17, 4, 92, 94, 95, 67, 69, 73, 75, 86, 37, 74, 50, 11, 79, 29, 15, 56, 43, 22, 83, 81, 61, 14, 3, 36, 44, 58, 10, 62, 19, 72, 80, 65, 24, 18, 5, 40, 90, 33, 9, 47, 76, 8, 59, 35, 91, 99, 13, 70, 88, 55, 16, 31, 28, 85, 45, 60, 25, 87, 82, 93, 12, 34, 68, 63, 26, 46, 48, 21, 52, 1, 78, 98, 38, 6, 32, 89, 53, 41, 57]], [[77, 99, 47, 64, 26, 63, 50, 81, 23, 45, 49, 36, 43, 56, 39, 12, 86, 62, 2, 98, 60, 94, 75, 9, 20, 74, 48, 28, 4, 84, 61, 31, 54, 15, 40, 7, 87, 38, 80, 6, 37, 46, 1, 55, 88, 73, 95, 33, 92, 18, 25, 66, 57, 27, 42, 35, 91, 51, 13, 90, 41, 83, 68, 53, 19, 3, 72, 89, 65, 70, 71, 8, 97, 59, 96, 52, 79, 22, 14, 69, 32, 93, 58, 29, 21, 76, 34, 5, 17, 67, 11, 78, 16, 0, 44, 30, 10, 24, 85, 82], [58, 62, 7, 39, 34, 69, 67, 73, 37, 59, 71, 66, 46, 57, 44, 51, 26, 85, 11, 28, 54, 47, 82, 21, 83, 76, 94, 16, 90, 95, 75, 55, 6, 22, 72, 74, 50, 40, 10, 19, 8, 53, 33, 98, 45, 87, 91, 13, 35, 70, 14, 38, 84, 99, 56, 30, 12, 89, 25, 97, 63, 65, 81, 92, 18, 29, 80, 61, 93, 43, 49, 52, 23, 31, 32, 4, 48, 3, 0, 78, 96, 64, 41, 88, 24, 5, 9, 15, 77, 86, 68, 1, 17, 79, 60, 36, 42, 2, 20, 27], [58, 62, 7, 39, 34, 69, 67, 73, 37, 59, 71, 66, 46, 57, 44, 51, 26, 85, 11, 28, 54, 47, 82, 21, 83, 76, 94, 16, 90, 95, 75, 55, 6, 22, 72, 74, 50, 40, 10, 19, 8, 53, 33, 98, 45, 87, 91, 13, 35, 70, 14, 38, 84, 99, 56, 30, 12, 89, 25, 97, 63, 65, 81, 92, 18, 29, 80, 61, 93, 43, 49, 52, 23, 31, 32, 4, 48, 3, 0, 78, 96, 64, 41, 88, 24, 5, 9, 15, 77, 86, 68, 1, 17, 79, 60, 36, 42, 2, 20, 27], [91, 43, 77, 69, 16, 96, 47, 34, 49, 15, 73, 84, 85, 22, 88, 95, 2, 80, 57, 33, 32, 41, 25, 14, 58, 9, 20, 65, 48, 97, 79, 89, 66, 63, 46, 83, 19, 92, 55, 18, 38, 0, 21, 50, 45, 62, 29, 26, 52, 28, 8, 6, 75, 86, 44, 81, 36, 90, 70, 30, 71, 39, 82, 87, 76, 1, 23, 5, 60, 98, 67, 53, 93, 72, 42, 74, 51, 4, 31, 59, 61, 7, 24, 56, 37, 54, 3, 11, 27, 40, 10, 64, 94, 35, 78, 68, 99, 17, 12, 13], [73, 70, 39, 9, 77, 61, 80, 10, 13, 92, 38, 4, 48, 57, 25, 72, 49, 51, 99, 97, 85, 36, 22, 15, 8, 34, 33, 76, 26, 45, 83, 59, 28, 96, 90, 47, 68, 88, 44, 6, 98, 12, 24, 46, 2, 54, 5, 58, 30, 63, 1, 18, 93, 67, 7, 50, 31, 16, 40, 56, 23, 86, 11, 52, 55, 75, 71, 27, 37, 87, 84, 65, 82, 29, 0, 14, 41, 35, 64, 21, 3, 95, 17, 60, 81, 74, 19, 91, 94, 32, 69, 53, 42, 89, 79, 43, 66, 20, 78, 62], [23, 78, 67, 41, 9, 77, 59, 72, 25, 82, 65, 89, 28, 37, 54, 70, 98, 33, 31, 44, 6, 17, 26, 73, 21, 36, 4, 2, 79, 95, 81, 50, 18, 34, 61, 0, 93, 24, 8, 66, 55, 62, 56, 30, 84, 58, 7, 88, 85, 64, 97, 39, 49, 3, 20, 42, 80, 96, 13, 63, 43, 60, 47, 90, 51, 14, 53, 1, 86, 57, 12, 19, 10, 45, 38, 68, 35, 87, 75, 5, 69, 27, 32, 91, 11, 99, 46, 29, 92, 22, 76, 15, 16, 48, 71, 74, 52, 94, 83, 40], [87, 89, 35, 98, 44, 21, 29, 83, 0, 77, 34, 60, 85, 64, 28, 58, 39, 36, 95, 22, 67, 30, 86, 57, 5, 81, 84, 26, 53, 62, 13, 90, 2, 88, 4, 46, 97, 73, 79, 43, 59, 72, 54, 32, 82, 10, 55, 38, 47, 12, 51, 1, 76, 48, 7, 14, 23, 20, 31, 18, 17, 15, 37, 42, 49, 68, 25, 93, 91, 40, 92, 50, 52, 70, 33, 80, 19, 96, 61, 75, 71, 99, 74, 9, 41, 66, 63, 8, 6, 24, 65, 56, 45, 69, 27, 16, 3, 78, 94, 11], [99, 6, 38, 11, 34, 28, 86, 57, 55, 78, 25, 95, 13, 63, 91, 14, 83, 1, 45, 17, 93, 76, 46, 79, 27, 85, 96, 58, 59, 44, 87, 65, 97, 22, 0, 51, 49, 52, 47, 67, 24, 88, 62, 50, 72, 3, 31, 82, 68, 42, 81, 23, 32, 98, 73, 60, 37, 54, 41, 80, 66, 18, 92, 4, 5, 94, 77, 39, 69, 16, 35, 7, 40, 30, 61, 26, 56, 64, 9, 71, 19, 21, 75, 84, 43, 53, 33, 29, 74, 36, 90, 2, 20, 15, 10, 48, 89, 70, 8, 12], [4, 28, 8, 72, 74, 31, 66, 0, 27, 54, 61, 23, 51, 73, 96, 32, 98, 41, 88, 95, 36, 22, 13, 38, 70, 84, 12, 7, 10, 60, 68, 33, 11, 35, 79, 42, 16, 62, 57, 24, 44, 94, 25, 48, 86, 97, 87, 49, 92, 71, 21, 1, 81, 5, 17, 85, 6, 75, 80, 34, 20, 30, 90, 69, 18, 89, 93, 56, 91, 40, 77, 52, 53, 14, 65, 45, 76, 2, 9, 29, 3, 26, 59, 55, 83, 46, 67, 47, 39, 50, 58, 63, 99, 15, 37, 43, 82, 64, 78, 19], [11, 94, 1, 93, 59, 91, 89, 51, 61, 81, 13, 29, 27, 58, 26, 3, 53, 69, 73, 21, 39, 12, 5, 18, 98, 74, 9, 96, 28, 65, 23, 4, 41, 72, 88, 34, 83, 54, 7, 15, 38, 84, 90, 52, 77, 48, 64, 60, 20, 79, 19, 66, 97, 30, 87, 45, 40, 36, 14, 86, 32, 33, 57, 16, 43, 42, 50, 10, 44, 76, 37, 6, 56, 31, 68, 99, 2, 17, 22, 35, 92, 85, 46, 75, 71, 67, 95, 78, 8, 63, 82, 25, 80, 24, 47, 49, 0, 70, 62, 55]], [[93, 99, 51, 49, 71, 64, 35, 42, 88, 17, 67, 92, 4, 12, 68, 13, 47, 7, 56, 14, 19, 53, 80, 85, 23, 5, 39, 6, 26, 89, 27, 54, 63, 73, 70, 33, 36, 3, 86, 58, 18, 2, 25, 21, 10, 34, 81, 94, 75, 98, 37, 46, 9, 95, 60, 74, 87, 78, 20, 24, 57, 0, 30, 83, 72, 61, 11, 32, 43, 82, 65, 69, 59, 62, 38, 76, 22, 16, 15, 45, 48, 79, 50, 90, 40, 1, 29, 77, 91, 31, 84, 96, 8, 52, 97, 41, 28, 44, 55, 66], [64, 71, 19, 27, 43, 95, 77, 16, 35, 81, 74, 29, 6, 86, 18, 37, 99, 46, 15, 87, 28, 63, 1, 65, 3, 79, 50, 12, 78, 84, 8, 88, 98, 69, 42, 0, 56, 32, 92, 83, 30, 59, 80, 9, 20, 89, 47, 23, 33, 34, 82, 24, 97, 60, 22, 90, 51, 76, 10, 94, 21, 91, 70, 49, 66, 14, 75, 2, 7, 13, 40, 93, 48, 36, 53, 72, 67, 62, 85, 17, 57, 58, 5, 25, 41, 31, 44, 73, 61, 26, 38, 54, 96, 39, 4, 68, 11, 52, 45, 55], [49, 88, 62, 73, 34, 15, 95, 68, 98, 5, 61, 35, 23, 45, 78, 64, 97, 70, 96, 65, 74, 16, 94, 37, 80, 56, 48, 28, 59, 1, 75, 4, 71, 47, 83, 93, 69, 21, 60, 38, 39, 19, 40, 82, 55, 7, 52, 18, 43, 54, 2, 77, 66, 90, 44, 32, 89, 3, 24, 6, 99, 17, 86, 29, 30, 22, 50, 81, 41, 42, 0, 9, 53, 58, 57, 25, 20, 12, 26, 51, 92, 87, 36, 31, 85, 63, 14, 8, 91, 11, 79, 27, 76, 84, 67, 33, 72, 13, 10, 46], [45, 15, 69, 88, 51, 28, 34, 80, 30, 42, 38, 90, 47, 17, 84, 49, 21, 55, 46, 96, 37, 97, 72, 85, 94, 29, 10, 66, 76, 82, 18, 86, 87, 25, 43, 92, 19, 89, 2, 93, 98, 40, 48, 53, 75, 99, 11, 62, 12, 60, 3, 24, 4, 6, 63, 81, 41, 20, 68, 9, 57, 52, 0, 44, 14, 16, 91, 27, 79, 73, 59, 61, 78, 7, 67, 1, 70, 83, 74, 64, 26, 95, 54, 65, 33, 39, 5, 50, 36, 35, 13, 23, 58, 71, 32, 77, 31, 22, 56, 8], [41, 43, 66, 69, 22, 23, 71, 2, 33, 38, 86, 51, 55, 59, 82, 96, 45, 97, 73, 34, 70, 21, 8, 58, 84, 90, 24, 25, 32, 78, 17, 27, 47, 68, 37, 72, 63, 77, 87, 89, 50, 16, 83, 54, 12, 56, 64, 62, 39, 92, 91, 53, 29, 76, 52, 94, 42, 81, 20, 98, 40, 79, 44, 10, 31, 0, 57, 19, 75, 67, 93, 6, 7, 11, 74, 26, 85, 5, 1, 49, 4, 61, 95, 3, 36, 9, 14, 13, 15, 48, 80, 46, 30, 65, 99, 18, 60, 88, 35, 28], [5, 56, 10, 81, 42, 35, 12, 94, 34, 13, 8, 0, 49, 17, 7, 69, 30, 1, 65, 14, 39, 2, 58, 76, 54, 31, 50, 46, 11, 27, 22, 61, 74, 64, 91, 18, 48, 63, 71, 57, 95, 87, 47, 67, 77, 53, 88, 23, 3, 83, 29, 86, 43, 60, 70, 78, 21, 99, 36, 66, 20, 62, 85, 4, 80, 98, 79, 82, 97, 15, 96, 52, 51, 6, 40, 93, 28, 41, 72, 45, 68, 16, 32, 75, 84, 89, 26, 55, 9, 59, 73, 24, 25, 33, 37, 19, 90, 44, 38, 92], [62, 28, 97, 69, 65, 46, 27, 96, 29, 73, 89, 42, 16, 36, 44, 63, 80, 60, 11, 54, 87, 92, 75, 81, 57, 26, 70, 49, 76, 10, 95, 84, 56, 22, 20, 9, 21, 61, 1, 47, 34, 19, 66, 0, 33, 91, 45, 3, 2, 90, 88, 43, 51, 12, 7, 18, 24, 85, 86, 8, 78, 38, 55, 30, 6, 35, 15, 93, 14, 99, 98, 82, 52, 74, 4, 50, 79, 37, 77, 17, 41, 71, 58, 53, 68, 39, 67, 25, 5, 83, 94, 13, 48, 32, 23, 59, 31, 64, 72, 40], [93, 20, 18, 22, 94, 27, 39, 59, 4, 11, 6, 75, 98, 62, 63, 81, 44, 53, 25, 95, 74, 57, 76, 5, 70, 60, 99, 12, 56, 85, 41, 67, 46, 19, 28, 1, 23, 80, 32, 68, 31, 51, 82, 55, 78, 77, 58, 69, 38, 87, 91, 79, 96, 52, 47, 73, 83, 89, 65, 3, 92, 14, 43, 66, 61, 37, 84, 54, 33, 88, 35, 71, 42, 90, 72, 50, 7, 40, 0, 24, 9, 29, 49, 45, 15, 21, 86, 64, 16, 36, 34, 17, 26, 10, 2, 13, 8, 97, 30, 48], [33, 3, 7, 64, 74, 23, 42, 25, 68, 85, 5, 8, 83, 17, 56, 79, 70, 73, 15, 6, 36, 18, 94, 97, 72, 22, 11, 96, 40, 58, 66, 49, 62, 86, 78, 67, 26, 98, 90, 48, 14, 2, 82, 91, 9, 76, 69, 44, 50, 47, 53, 71, 92, 12, 59, 37, 19, 60, 39, 13, 77, 16, 55, 41, 84, 31, 65, 27, 99, 51, 4, 45, 80, 46, 57, 21, 28, 81, 54, 29, 61, 88, 52, 43, 75, 20, 1, 10, 0, 35, 30, 32, 95, 38, 63, 87, 89, 24, 34, 93], [37, 25, 50, 66, 86, 23, 76, 27, 83, 97, 89, 35, 32, 41, 33, 87, 14, 59, 48, 61, 52, 3, 73, 67, 24, 56, 93, 22, 7, 70, 77, 28, 91, 30, 68, 29, 60, 8, 94, 13, 43, 17, 88, 57, 81, 34, 15, 95, 79, 96, 72, 84, 55, 46, 58, 10, 12, 38, 11, 99, 53, 42, 65, 44, 31, 21, 82, 6, 92, 26, 51, 5, 39, 63, 40, 9, 49, 18, 78, 80, 71, 74, 90, 2, 54, 47, 85, 75, 69, 45, 0, 16, 19, 1, 64, 98, 4, 62, 36, 20]]];\nconst sbtable2 = [[3, 5, 8, 6, 0, 9, 7, 1, 2, 4], [1, 3, 9, 4, 2, 0, 8, 7, 5, 6], [0, 5, 1, 7, 9, 8, 6, 2, 3, 4], [6, 4, 7, 8, 3, 0, 9, 5, 2, 1], [2, 3, 8, 1, 9, 7, 6, 0, 4, 5], [3, 4, 1, 7, 2, 8, 6, 0, 9, 5], [6, 1, 8, 3, 0, 4, 2, 7, 5, 9], [9, 3, 7, 5, 2, 4, 0, 6, 1, 8], [6, 1, 5, 3, 0, 8, 7, 4, 2, 9], [9, 7, 4, 5, 1, 2, 3, 0, 8, 6]];\n\nconst ibtable = [[[11, 38, 3, 63, 36, 39, 79, 19, 87, 68, 76, 51, 20, 56, 77, 61, 52, 73, 74, 94, 45, 31, 99, 28, 29, 90, 81, 96, 65, 75, 13, 32, 70, 21, 55, 33, 9, 15, 92, 14, 82, 97, 78, 37, 49, 0, 80, 57, 58, 7, 1, 89, 98, 53, 64, 5, 6, 66, 43, 83, 10, 50, 47, 84, 62, 71, 4, 67, 86, 42, 35, 34, 91, 12, 17, 69, 44, 48, 85, 30, 16, 95, 54, 23, 46, 18, 88, 59, 40, 60, 41, 25, 27, 22, 2, 24, 72, 93, 26, 8], [28, 58, 74, 34, 6, 14, 16, 46, 87, 24, 59, 57, 23, 88, 75, 65, 79, 38, 82, 13, 49, 99, 8, 94, 15, 19, 0, 96, 41, 95, 45, 35, 1, 91, 2, 52, 42, 76, 90, 84, 20, 54, 4, 63, 25, 5, 47, 85, 93, 12, 51, 81, 71, 69, 22, 17, 36, 64, 77, 80, 98, 53, 44, 18, 10, 68, 97, 61, 56, 70, 92, 27, 40, 9, 60, 7, 72, 21, 43, 3, 33, 32, 50, 26, 67, 62, 39, 48, 73, 86, 29, 89, 37, 78, 55, 66, 31, 30, 11, 83], [4, 16, 22, 66, 37, 14, 47, 89, 59, 60, 51, 92, 71, 70, 96, 13, 17, 85, 58, 93, 81, 69, 28, 90, 78, 39, 63, 88, 0, 75, 2, 53, 23, 99, 94, 68, 54, 74, 41, 29, 8, 26, 50, 98, 82, 95, 42, 7, 24, 77, 30, 9, 21, 1, 87, 62, 46, 15, 43, 38, 36, 55, 49, 57, 52, 56, 91, 65, 11, 84, 6, 73, 97, 33, 83, 27, 35, 25, 40, 32, 18, 31, 86, 48, 45, 3, 79, 76, 72, 64, 44, 20, 80, 19, 10, 5, 61, 34, 67, 12], [80, 91, 71, 26, 75, 8, 22, 92, 7, 70, 65, 51, 89, 31, 81, 30, 83, 47, 44, 85, 55, 19, 57, 87, 74, 6, 73, 40, 49, 32, 52, 78, 0, 12, 54, 15, 64, 28, 4, 24, 68, 17, 72, 53, 1, 94, 58, 88, 11, 82, 43, 86, 60, 63, 99, 96, 37, 77, 67, 33, 18, 5, 41, 59, 16, 36, 79, 97, 61, 23, 56, 48, 98, 38, 66, 21, 34, 29, 10, 3, 93, 46, 50, 39, 14, 9, 2, 13, 69, 42, 62, 35, 27, 90, 25, 76, 20, 95, 45, 84], [48, 16, 54, 47, 9, 39, 81, 91, 33, 53, 63, 21, 50, 85, 97, 90, 49, 36, 84, 74, 51, 76, 37, 67, 59, 58, 23, 20, 65, 82, 7, 77, 12, 31, 46, 1, 5, 14, 3, 30, 94, 95, 2, 34, 70, 89, 40, 87, 43, 79, 64, 57, 68, 26, 56, 44, 88, 61, 0, 24, 71, 18, 60, 4, 80, 96, 27, 15, 6, 13, 98, 29, 28, 25, 72, 93, 55, 75, 52, 66, 11, 8, 86, 45, 22, 83, 17, 10, 35, 38, 73, 99, 62, 41, 19, 69, 78, 92, 42, 32], [23, 19, 88, 44, 5, 39, 75, 81, 30, 14, 49, 54, 62, 55, 18, 83, 77, 76, 74, 92, 6, 95, 52, 36, 15, 27, 53, 38, 28, 50, 48, 99, 78, 67, 90, 87, 16, 41, 58, 65, 79, 11, 68, 84, 24, 97, 64, 47, 9, 22, 43, 86, 37, 8, 33, 17, 93, 61, 25, 72, 57, 98, 42, 80, 13, 89, 2, 12, 31, 56, 26, 85, 3, 29, 66, 63, 82, 10, 20, 94, 51, 0, 1, 4, 21, 60, 34, 35, 32, 45, 59, 71, 46, 69, 7, 96, 91, 40, 70, 73], [89, 62, 33, 19, 21, 97, 15, 2, 83, 22, 65, 30, 55, 7, 63, 73, 39, 61, 44, 37, 11, 26, 31, 79, 91, 0, 72, 68, 23, 87, 28, 24, 45, 74, 98, 14, 70, 54, 88, 42, 35, 59, 46, 16, 27, 92, 69, 66, 94, 32, 75, 77, 64, 57, 50, 71, 10, 3, 67, 81, 90, 58, 99, 5, 82, 85, 25, 52, 12, 8, 48, 49, 76, 96, 80, 20, 29, 34, 53, 51, 86, 93, 38, 84, 9, 36, 6, 60, 1, 78, 13, 95, 41, 17, 47, 18, 43, 40, 4, 56], [40, 68, 88, 47, 43, 28, 67, 23, 42, 99, 48, 3, 12, 27, 79, 25, 6, 55, 19, 80, 81, 62, 83, 69, 39, 73, 36, 30, 44, 82, 70, 52, 31, 34, 58, 74, 54, 2, 13, 45, 93, 49, 75, 72, 29, 87, 5, 7, 17, 76, 90, 63, 84, 51, 59, 35, 20, 97, 22, 65, 57, 66, 78, 86, 11, 9, 71, 98, 53, 56, 15, 46, 92, 0, 26, 21, 32, 38, 77, 91, 4, 24, 61, 85, 94, 1, 96, 64, 8, 41, 33, 50, 18, 60, 10, 16, 37, 95, 14, 89], [96, 23, 99, 42, 94, 91, 19, 53, 41, 25, 39, 73, 70, 72, 33, 35, 88, 2, 63, 49, 95, 60, 48, 97, 5, 54, 47, 40, 98, 18, 57, 28, 67, 92, 10, 79, 13, 76, 8, 55, 90, 62, 50, 87, 65, 82, 84, 21, 0, 14, 45, 44, 20, 38, 17, 3, 81, 16, 58, 4, 31, 29, 86, 15, 43, 64, 26, 52, 46, 69, 37, 68, 6, 22, 61, 7, 83, 71, 30, 75, 85, 78, 24, 27, 89, 9, 80, 34, 66, 77, 36, 93, 56, 59, 1, 12, 51, 32, 11, 74], [75, 99, 97, 8, 15, 48, 6, 25, 60, 90, 91, 95, 23, 3, 89, 77, 22, 78, 94, 55, 98, 35, 53, 96, 18, 52, 12, 16, 50, 20, 49, 9, 17, 13, 57, 44, 14, 47, 86, 56, 88, 41, 29, 32, 70, 1, 62, 37, 85, 38, 59, 36, 5, 68, 71, 69, 67, 27, 39, 4, 54, 0, 84, 45, 61, 73, 79, 93, 58, 66, 10, 76, 51, 92, 19, 87, 24, 7, 28, 2, 11, 80, 81, 33, 64, 74, 46, 65, 26, 72, 40, 82, 34, 42, 21, 83, 31, 30, 43, 63]], [[98, 58, 34, 65, 83, 74, 88, 5, 89, 46, 80, 43, 18, 87, 9, 28, 71, 90, 4, 36, 40, 11, 39, 31, 76, 92, 82, 48, 66, 41, 49, 99, 78, 79, 97, 86, 75, 68, 3, 7, 62, 64, 26, 22, 13, 77, 54, 50, 10, 96, 15, 35, 94, 73, 57, 93, 16, 61, 37, 38, 53, 2, 63, 23, 67, 72, 95, 70, 29, 33, 45, 47, 27, 24, 69, 44, 55, 85, 14, 8, 91, 12, 42, 6, 84, 81, 19, 25, 32, 51, 1, 17, 52, 56, 60, 0, 59, 30, 21, 20], [26, 63, 99, 57, 77, 53, 9, 75, 76, 80, 46, 97, 37, 14, 1, 12, 35, 20, 0, 15, 28, 19, 48, 41, 67, 30, 60, 69, 29, 34, 73, 10, 51, 47, 66, 82, 7, 98, 39, 96, 8, 62, 42, 3, 95, 5, 11, 13, 90, 94, 32, 31, 83, 64, 36, 88, 72, 52, 38, 54, 45, 17, 61, 81, 78, 44, 79, 55, 56, 86, 2, 40, 16, 24, 4, 71, 49, 33, 23, 92, 84, 74, 65, 43, 87, 59, 89, 68, 22, 70, 25, 58, 21, 85, 6, 50, 27, 93, 91, 18], [22, 31, 11, 72, 37, 70, 90, 60, 24, 56, 28, 69, 54, 85, 5, 98, 1, 76, 59, 20, 86, 32, 61, 49, 63, 42, 74, 53, 84, 3, 95, 23, 15, 36, 4, 81, 6, 21, 19, 27, 17, 83, 30, 45, 25, 65, 10, 50, 80, 66, 46, 75, 93, 82, 78, 99, 97, 68, 8, 13, 58, 94, 41, 14, 48, 52, 29, 79, 91, 89, 9, 55, 57, 2, 39, 92, 0, 44, 18, 62, 73, 96, 34, 88, 16, 77, 71, 43, 33, 40, 7, 12, 87, 51, 26, 47, 64, 35, 67, 38], [0, 80, 63, 52, 49, 69, 15, 87, 55, 60, 22, 91, 31, 89, 78, 28, 48, 12, 10, 42, 82, 23, 29, 18, 21, 2, 19, 7, 68, 37, 54, 90, 81, 43, 57, 94, 26, 95, 96, 88, 14, 51, 79, 71, 66, 76, 34, 24, 30, 9, 62, 44, 77, 65, 6, 27, 4, 97, 38, 36, 59, 3, 1, 50, 72, 46, 64, 35, 20, 11, 53, 13, 58, 39, 74, 8, 83, 75, 40, 98, 17, 99, 85, 32, 92, 67, 84, 5, 25, 56, 16, 47, 70, 93, 86, 61, 73, 41, 45, 33], [64, 57, 56, 7, 86, 9, 65, 16, 1, 63, 71, 26, 53, 98, 69, 5, 84, 28, 36, 58, 54, 99, 42, 74, 68, 3, 88, 22, 82, 97, 85, 45, 21, 66, 43, 59, 83, 51, 89, 87, 31, 12, 95, 52, 60, 17, 80, 27, 72, 93, 10, 39, 91, 30, 75, 61, 24, 8, 23, 2, 18, 73, 94, 6, 38, 44, 13, 40, 48, 4, 81, 37, 96, 46, 19, 49, 34, 50, 0, 20, 14, 15, 25, 92, 33, 29, 77, 90, 78, 67, 62, 41, 35, 47, 79, 32, 11, 70, 76, 55], [24, 99, 28, 52, 64, 3, 63, 16, 15, 87, 47, 6, 59, 98, 13, 78, 57, 81, 56, 94, 0, 37, 70, 73, 65, 83, 90, 92, 60, 82, 67, 40, 74, 34, 91, 2, 33, 85, 21, 54, 12, 31, 84, 55, 53, 49, 36, 25, 39, 20, 29, 93, 51, 76, 42, 96, 71, 86, 95, 66, 45, 19, 8, 58, 22, 69, 80, 79, 89, 17, 61, 18, 88, 38, 72, 75, 48, 30, 7, 10, 11, 35, 23, 9, 26, 4, 62, 44, 1, 43, 46, 14, 41, 77, 97, 27, 68, 32, 5, 50], [90, 80, 22, 27, 16, 23, 11, 31, 8, 75, 54, 82, 68, 66, 10, 40, 95, 99, 14, 42, 56, 88, 12, 55, 38, 6, 79, 84, 26, 92, 4, 67, 48, 5, 46, 77, 19, 53, 97, 34, 64, 73, 58, 47, 18, 39, 81, 59, 74, 62, 87, 98, 50, 1, 25, 9, 72, 69, 61, 60, 86, 3, 24, 28, 45, 30, 96, 36, 57, 83, 89, 63, 0, 33, 17, 7, 94, 15, 43, 2, 44, 41, 20, 85, 32, 65, 93, 49, 91, 52, 71, 37, 35, 13, 21, 51, 70, 29, 78, 76], [95, 50, 72, 0, 68, 98, 49, 53, 56, 41, 54, 22, 57, 78, 66, 31, 52, 29, 86, 30, 62, 26, 32, 46, 42, 48, 14, 21, 88, 94, 77, 92, 7, 63, 91, 28, 93, 38, 90, 71, 34, 25, 11, 83, 55, 70, 97, 82, 89, 76, 10, 99, 9, 45, 60, 39, 44, 16, 17, 37, 47, 79, 33, 36, 59, 8, 80, 23, 1, 18, 64, 51, 61, 81, 75, 40, 35, 73, 13, 65, 12, 4, 19, 85, 96, 6, 2, 58, 27, 43, 5, 87, 20, 15, 3, 24, 84, 67, 74, 69], [38, 33, 29, 88, 49, 47, 60, 69, 75, 12, 44, 89, 35, 45, 23, 30, 21, 28, 65, 86, 81, 40, 93, 97, 67, 2, 94, 9, 61, 92, 90, 32, 62, 36, 58, 51, 37, 73, 50, 63, 39, 43, 16, 71, 46, 91, 13, 7, 20, 72, 41, 59, 70, 48, 10, 52, 5, 34, 76, 15, 87, 6, 98, 18, 57, 77, 24, 79, 27, 19, 3, 0, 8, 95, 74, 64, 42, 4, 68, 31, 84, 54, 99, 25, 1, 80, 85, 26, 83, 11, 56, 55, 78, 66, 82, 14, 53, 22, 17, 96], [26, 12, 62, 5, 78, 53, 31, 46, 51, 8, 69, 80, 32, 68, 76, 42, 29, 87, 28, 75, 40, 91, 58, 7, 88, 92, 82, 96, 70, 50, 47, 65, 85, 3, 48, 73, 90, 89, 97, 84, 81, 39, 43, 79, 64, 54, 2, 41, 38, 10, 24, 22, 25, 93, 44, 23, 49, 37, 14, 95, 72, 74, 15, 11, 55, 98, 99, 0, 9, 16, 18, 20, 63, 30, 57, 19, 4, 17, 67, 35, 60, 45, 59, 56, 36, 77, 66, 33, 27, 71, 86, 1, 13, 34, 21, 61, 6, 94, 52, 83]], [[10, 87, 64, 11, 25, 97, 93, 18, 99, 38, 17, 72, 50, 23, 90, 57, 98, 12, 29, 46, 19, 77, 42, 15, 73, 52, 53, 89, 35, 20, 9, 41, 79, 13, 95, 48, 85, 54, 61, 94, 0, 74, 62, 40, 78, 68, 24, 28, 86, 21, 59, 14, 82, 84, 92, 58, 34, 31, 6, 16, 75, 81, 43, 47, 7, 3, 2, 37, 67, 8, 66, 22, 30, 32, 71, 44, 70, 1, 36, 26, 33, 63, 80, 83, 91, 76, 56, 39, 69, 55, 96, 60, 27, 49, 65, 88, 5, 4, 51, 45], [73, 87, 48, 43, 71, 40, 88, 23, 60, 35, 30, 5, 75, 25, 59, 95, 58, 79, 4, 89, 96, 17, 38, 6, 39, 9, 68, 81, 3, 90, 93, 99, 16, 42, 21, 45, 74, 84, 77, 65, 63, 98, 11, 51, 0, 33, 91, 22, 69, 34, 31, 20, 46, 2, 76, 54, 15, 62, 13, 70, 92, 55, 82, 47, 78, 7, 24, 27, 86, 1, 56, 61, 12, 44, 85, 57, 49, 19, 18, 67, 66, 52, 72, 53, 83, 41, 64, 50, 26, 94, 32, 80, 28, 10, 37, 14, 8, 97, 29, 36], [60, 50, 53, 78, 63, 90, 11, 33, 21, 24, 20, 55, 8, 25, 6, 58, 3, 98, 44, 82, 96, 14, 1, 59, 92, 75, 51, 36, 30, 64, 72, 40, 16, 94, 2, 74, 93, 85, 12, 10, 43, 32, 42, 39, 79, 97, 17, 38, 89, 29, 68, 52, 49, 0, 34, 19, 70, 84, 54, 9, 23, 71, 65, 28, 83, 56, 67, 57, 13, 18, 77, 5, 4, 88, 41, 22, 46, 76, 48, 61, 81, 45, 86, 35, 47, 87, 91, 99, 73, 66, 27, 37, 31, 15, 7, 80, 62, 95, 69, 26], [49, 73, 63, 66, 38, 35, 32, 96, 87, 26, 36, 92, 58, 6, 17, 47, 29, 84, 11, 18, 67, 45, 78, 4, 52, 81, 59, 30, 91, 54, 56, 89, 48, 46, 20, 79, 1, 62, 9, 53, 10, 95, 88, 34, 40, 80, 41, 64, 83, 55, 43, 7, 24, 61, 77, 5, 14, 93, 16, 21, 85, 39, 76, 50, 57, 65, 37, 60, 28, 19, 2, 97, 42, 33, 13, 68, 90, 25, 69, 99, 98, 74, 3, 8, 12, 15, 82, 71, 31, 23, 75, 27, 51, 94, 86, 0, 44, 22, 72, 70], [30, 32, 52, 21, 15, 79, 53, 40, 56, 44, 55, 6, 63, 39, 61, 4, 93, 43, 23, 99, 38, 66, 88, 18, 1, 86, 33, 9, 82, 76, 70, 51, 48, 69, 85, 11, 5, 91, 59, 77, 49, 75, 22, 87, 65, 41, 26, 50, 47, 98, 57, 10, 58, 62, 46, 28, 20, 71, 78, 95, 0, 72, 80, 73, 92, 36, 96, 37, 68, 2, 35, 83, 90, 25, 13, 24, 34, 42, 45, 74, 67, 16, 84, 97, 19, 64, 27, 14, 31, 12, 54, 60, 3, 8, 17, 89, 81, 94, 7, 29], [1, 18, 25, 13, 57, 53, 92, 95, 94, 88, 10, 82, 34, 83, 7, 28, 55, 11, 5, 58, 8, 9, 74, 99, 52, 32, 62, 45, 65, 50, 41, 56, 96, 44, 38, 47, 3, 39, 81, 19, 2, 22, 49, 12, 40, 67, 89, 76, 64, 70, 61, 21, 31, 54, 51, 17, 46, 30, 24, 60, 66, 26, 77, 63, 37, 35, 23, 6, 4, 87, 79, 97, 20, 48, 36, 85, 73, 71, 27, 43, 0, 15, 69, 78, 59, 86, 75, 33, 42, 84, 91, 93, 68, 80, 16, 98, 90, 72, 14, 29], [30, 16, 10, 67, 83, 81, 42, 94, 35, 59, 22, 5, 53, 61, 1, 96, 68, 45, 95, 66, 36, 37, 97, 87, 77, 93, 86, 33, 49, 13, 43, 14, 0, 34, 7, 2, 41, 21, 31, 32, 76, 55, 62, 72, 90, 71, 38, 23, 46, 12, 51, 19, 6, 44, 52, 48, 73, 24, 29, 74, 85, 99, 80, 28, 47, 9, 39, 84, 64, 57, 75, 98, 88, 26, 17, 63, 27, 56, 69, 8, 54, 25, 91, 78, 3, 50, 65, 70, 11, 4, 92, 60, 40, 58, 15, 89, 82, 18, 79, 20], [60, 88, 79, 35, 40, 43, 52, 4, 17, 31, 84, 44, 50, 94, 91, 38, 87, 25, 92, 62, 14, 97, 37, 18, 86, 28, 65, 90, 19, 29, 30, 75, 68, 49, 69, 11, 59, 41, 89, 33, 47, 54, 98, 42, 80, 56, 78, 99, 23, 82, 9, 48, 21, 1, 63, 22, 58, 95, 10, 12, 26, 74, 85, 13, 8, 27, 24, 53, 61, 34, 64, 71, 66, 32, 83, 73, 15, 67, 0, 20, 16, 6, 77, 45, 5, 93, 76, 39, 57, 2, 96, 46, 51, 3, 55, 7, 81, 70, 36, 72], [35, 56, 77, 58, 23, 83, 91, 81, 53, 70, 20, 74, 84, 50, 79, 51, 88, 44, 45, 71, 37, 26, 54, 48, 27, 43, 0, 12, 95, 97, 1, 63, 67, 98, 59, 40, 13, 19, 31, 87, 99, 16, 57, 30, 17, 92, 55, 68, 5, 46, 64, 8, 7, 42, 90, 33, 29, 9, 85, 24, 2, 69, 32, 10, 21, 65, 39, 86, 52, 62, 76, 89, 82, 6, 78, 4, 47, 28, 3, 75, 41, 15, 18, 14, 66, 73, 38, 80, 61, 49, 11, 22, 34, 93, 36, 25, 94, 96, 60, 72], [6, 90, 16, 43, 20, 55, 94, 8, 62, 59, 47, 32, 81, 67, 42, 35, 71, 19, 54, 49, 2, 88, 38, 5, 53, 77, 85, 11, 73, 34, 3, 72, 95, 58, 82, 64, 44, 29, 93, 14, 56, 98, 4, 37, 45, 75, 86, 60, 87, 7, 31, 17, 89, 97, 10, 70, 36, 99, 46, 63, 76, 41, 48, 84, 9, 52, 1, 24, 83, 25, 68, 18, 50, 26, 30, 27, 61, 0, 91, 33, 51, 40, 79, 39, 15, 74, 28, 78, 69, 96, 57, 65, 21, 80, 22, 23, 12, 13, 92, 66]], [[93, 42, 18, 65, 28, 87, 39, 35, 71, 23, 96, 90, 15, 58, 78, 33, 92, 88, 49, 64, 24, 84, 77, 8, 97, 50, 4, 53, 27, 83, 95, 31, 80, 47, 86, 55, 11, 40, 37, 14, 34, 60, 54, 12, 94, 9, 41, 2, 26, 10, 6, 57, 75, 63, 32, 43, 13, 52, 82, 73, 20, 30, 17, 5, 3, 68, 51, 89, 62, 79, 69, 70, 66, 45, 25, 22, 85, 0, 91, 76, 38, 7, 99, 61, 29, 98, 16, 36, 44, 67, 59, 56, 48, 81, 21, 46, 74, 72, 19, 1], [78, 91, 97, 77, 75, 85, 32, 2, 40, 86, 38, 18, 56, 47, 50, 87, 27, 92, 64, 39, 98, 23, 33, 72, 84, 58, 16, 99, 19, 65, 55, 73, 74, 42, 4, 48, 95, 8, 51, 3, 37, 82, 96, 69, 14, 44, 12, 21, 76, 70, 36, 15, 71, 41, 20, 31, 54, 13, 0, 9, 94, 67, 1, 60, 81, 61, 11, 6, 90, 5, 49, 10, 34, 7, 35, 30, 25, 88, 79, 93, 66, 62, 22, 24, 52, 17, 89, 45, 83, 57, 28, 46, 63, 68, 26, 29, 80, 59, 43, 53], [78, 91, 97, 77, 75, 85, 32, 2, 40, 86, 38, 18, 56, 47, 50, 87, 27, 92, 64, 39, 98, 23, 33, 72, 84, 58, 16, 99, 19, 65, 55, 73, 74, 42, 4, 48, 95, 8, 51, 3, 37, 82, 96, 69, 14, 44, 12, 21, 76, 70, 36, 15, 71, 41, 20, 31, 54, 13, 0, 9, 94, 67, 1, 60, 81, 61, 11, 6, 90, 5, 49, 10, 34, 7, 35, 30, 25, 88, 79, 93, 66, 62, 22, 24, 52, 17, 89, 45, 83, 57, 28, 46, 63, 68, 26, 29, 80, 59, 43, 53], [41, 65, 16, 86, 77, 67, 51, 81, 50, 25, 90, 87, 98, 99, 23, 9, 4, 97, 39, 36, 26, 42, 13, 66, 82, 22, 47, 88, 49, 46, 59, 78, 20, 19, 7, 93, 56, 84, 40, 61, 89, 21, 74, 1, 54, 44, 34, 6, 28, 8, 43, 76, 48, 71, 85, 38, 83, 18, 24, 79, 68, 80, 45, 33, 91, 27, 32, 70, 95, 3, 58, 60, 73, 10, 75, 52, 64, 2, 94, 30, 17, 55, 62, 35, 11, 12, 53, 63, 14, 31, 57, 0, 37, 72, 92, 15, 5, 29, 69, 96], [74, 50, 44, 80, 11, 46, 39, 54, 24, 3, 7, 62, 41, 8, 75, 23, 57, 82, 51, 86, 97, 79, 22, 60, 42, 14, 28, 67, 32, 73, 48, 56, 89, 26, 25, 77, 21, 68, 10, 2, 58, 76, 92, 95, 38, 29, 43, 35, 12, 16, 55, 17, 63, 91, 45, 64, 59, 13, 47, 31, 83, 5, 99, 49, 78, 71, 96, 53, 36, 90, 1, 66, 15, 0, 85, 65, 27, 4, 98, 94, 6, 84, 72, 30, 70, 20, 61, 69, 37, 93, 34, 87, 9, 52, 88, 81, 33, 19, 40, 18], [35, 67, 27, 53, 26, 79, 20, 46, 38, 4, 72, 84, 70, 58, 65, 91, 92, 21, 32, 71, 54, 24, 89, 0, 37, 8, 22, 81, 12, 87, 43, 18, 82, 17, 33, 76, 25, 13, 74, 51, 99, 3, 55, 60, 19, 73, 86, 62, 93, 52, 31, 64, 96, 66, 14, 40, 42, 69, 45, 6, 61, 34, 41, 59, 49, 10, 39, 2, 75, 80, 15, 94, 7, 23, 95, 78, 90, 5, 1, 28, 56, 30, 9, 98, 44, 48, 68, 77, 47, 11, 63, 83, 88, 36, 97, 29, 57, 50, 16, 85], [8, 51, 32, 96, 34, 24, 88, 54, 87, 83, 45, 99, 49, 30, 55, 61, 95, 60, 59, 76, 57, 5, 19, 56, 89, 66, 27, 94, 14, 6, 21, 58, 43, 74, 10, 2, 17, 62, 47, 16, 69, 84, 63, 39, 4, 92, 35, 48, 53, 64, 71, 50, 72, 28, 42, 46, 91, 23, 15, 40, 11, 78, 29, 86, 13, 90, 85, 20, 65, 93, 73, 80, 41, 37, 82, 79, 52, 9, 97, 38, 75, 25, 44, 7, 26, 12, 22, 0, 33, 1, 31, 68, 70, 67, 98, 18, 77, 36, 3, 81], [34, 17, 91, 45, 63, 64, 1, 71, 98, 78, 94, 3, 99, 12, 15, 93, 69, 19, 61, 80, 92, 81, 33, 51, 40, 10, 75, 24, 5, 87, 73, 46, 52, 86, 4, 70, 89, 56, 2, 67, 72, 58, 49, 84, 29, 18, 22, 38, 95, 36, 43, 35, 37, 85, 57, 8, 76, 7, 27, 28, 55, 74, 42, 13, 77, 31, 60, 39, 48, 68, 97, 79, 44, 54, 88, 82, 21, 66, 9, 23, 59, 50, 47, 16, 83, 25, 6, 30, 41, 96, 90, 14, 62, 20, 65, 11, 26, 32, 53, 0], [7, 51, 77, 80, 0, 53, 56, 27, 2, 78, 28, 32, 26, 22, 73, 93, 36, 54, 64, 99, 60, 50, 21, 11, 39, 42, 81, 8, 1, 79, 61, 5, 15, 31, 59, 33, 20, 94, 23, 88, 69, 17, 35, 95, 40, 75, 85, 87, 43, 47, 89, 12, 71, 72, 9, 83, 67, 38, 90, 82, 29, 10, 37, 91, 97, 74, 6, 86, 30, 63, 24, 49, 3, 13, 4, 57, 76, 70, 98, 34, 58, 52, 96, 84, 25, 55, 44, 46, 18, 65, 62, 68, 48, 66, 41, 19, 14, 45, 16, 92], [96, 2, 76, 15, 31, 22, 71, 38, 88, 26, 67, 0, 21, 10, 58, 39, 63, 77, 23, 50, 48, 19, 78, 30, 93, 91, 14, 12, 28, 11, 53, 73, 60, 61, 35, 79, 57, 70, 40, 20, 56, 32, 65, 64, 68, 55, 82, 94, 45, 95, 66, 7, 43, 16, 37, 99, 72, 62, 13, 4, 47, 8, 98, 89, 46, 29, 51, 85, 74, 17, 97, 84, 33, 18, 25, 83, 69, 44, 87, 49, 92, 9, 90, 36, 41, 81, 59, 54, 34, 6, 42, 5, 80, 3, 1, 86, 27, 52, 24, 75]], [[61, 85, 41, 37, 12, 25, 27, 17, 92, 52, 44, 66, 13, 15, 19, 78, 77, 9, 40, 20, 58, 43, 76, 24, 59, 42, 28, 30, 96, 86, 62, 89, 67, 35, 45, 6, 36, 50, 74, 26, 84, 95, 7, 68, 97, 79, 51, 16, 80, 3, 82, 2, 93, 21, 31, 98, 18, 60, 39, 72, 54, 65, 73, 32, 5, 70, 99, 10, 14, 71, 34, 4, 64, 33, 55, 48, 75, 87, 57, 81, 22, 46, 69, 63, 90, 23, 38, 56, 8, 29, 83, 88, 11, 0, 47, 53, 91, 94, 49, 1], [35, 22, 67, 24, 94, 82, 12, 68, 30, 43, 58, 96, 27, 69, 65, 18, 7, 79, 14, 2, 44, 60, 54, 47, 51, 83, 89, 3, 20, 11, 40, 85, 37, 48, 49, 8, 73, 15, 90, 93, 70, 84, 34, 4, 86, 98, 17, 46, 72, 63, 26, 56, 97, 74, 91, 99, 36, 80, 81, 41, 53, 88, 77, 21, 0, 23, 64, 76, 95, 33, 62, 1, 75, 87, 10, 66, 57, 6, 28, 25, 42, 9, 50, 39, 29, 78, 13, 19, 31, 45, 55, 61, 38, 71, 59, 5, 92, 52, 32, 16], [70, 29, 50, 57, 31, 9, 59, 45, 87, 71, 98, 89, 77, 97, 86, 5, 21, 61, 47, 41, 76, 37, 65, 12, 58, 75, 78, 91, 27, 63, 64, 83, 55, 95, 4, 11, 82, 23, 39, 40, 42, 68, 69, 48, 54, 13, 99, 33, 26, 0, 66, 79, 46, 72, 49, 44, 25, 74, 73, 28, 38, 10, 2, 85, 15, 19, 52, 94, 7, 36, 17, 32, 96, 3, 20, 30, 92, 51, 14, 90, 24, 67, 43, 34, 93, 84, 62, 81, 1, 56, 53, 88, 80, 35, 22, 6, 18, 16, 8, 60], [62, 75, 38, 50, 52, 86, 53, 73, 99, 59, 26, 46, 48, 90, 64, 1, 65, 13, 30, 36, 57, 16, 97, 91, 51, 33, 80, 67, 5, 25, 8, 96, 94, 84, 6, 89, 88, 20, 10, 85, 41, 56, 9, 34, 63, 0, 18, 12, 42, 15, 87, 4, 61, 43, 82, 17, 98, 60, 92, 70, 49, 71, 47, 54, 79, 83, 27, 74, 58, 2, 76, 93, 22, 69, 78, 44, 28, 95, 72, 68, 7, 55, 29, 77, 14, 23, 31, 32, 3, 37, 11, 66, 35, 39, 24, 81, 19, 21, 40, 45], [65, 78, 7, 83, 80, 77, 71, 72, 22, 85, 63, 73, 44, 87, 86, 88, 41, 30, 95, 67, 58, 21, 4, 5, 26, 27, 75, 31, 99, 52, 92, 64, 28, 8, 19, 98, 84, 34, 9, 48, 60, 0, 56, 1, 62, 16, 91, 32, 89, 79, 40, 11, 54, 51, 43, 12, 45, 66, 23, 13, 96, 81, 47, 36, 46, 93, 2, 69, 33, 3, 20, 6, 35, 18, 74, 68, 53, 37, 29, 61, 90, 57, 14, 42, 24, 76, 10, 38, 97, 39, 25, 50, 49, 70, 55, 82, 15, 17, 59, 94], [11, 17, 21, 48, 63, 0, 73, 14, 10, 88, 2, 28, 6, 9, 19, 69, 81, 13, 35, 95, 60, 56, 30, 47, 91, 92, 86, 29, 76, 50, 16, 25, 82, 93, 8, 5, 58, 94, 98, 20, 74, 77, 4, 52, 97, 79, 27, 42, 36, 12, 26, 72, 71, 45, 24, 87, 1, 39, 22, 89, 53, 31, 61, 37, 33, 18, 59, 43, 80, 15, 54, 38, 78, 90, 32, 83, 23, 44, 55, 66, 64, 3, 67, 49, 84, 62, 51, 41, 46, 85, 96, 34, 99, 75, 7, 40, 70, 68, 65, 57], [43, 38, 48, 47, 74, 88, 64, 54, 59, 35, 29, 18, 53, 91, 68, 66, 12, 79, 55, 41, 34, 36, 33, 94, 56, 87, 25, 6, 1, 8, 63, 96, 93, 44, 40, 65, 13, 77, 61, 85, 99, 80, 11, 51, 14, 46, 5, 39, 92, 27, 75, 52, 72, 83, 19, 62, 32, 24, 82, 95, 17, 37, 0, 15, 97, 4, 42, 86, 84, 3, 26, 81, 98, 9, 73, 22, 28, 78, 60, 76, 16, 23, 71, 89, 31, 57, 58, 20, 50, 10, 49, 45, 21, 67, 90, 30, 7, 2, 70, 69], [78, 35, 94, 59, 8, 23, 10, 76, 96, 80, 93, 9, 27, 95, 61, 84, 88, 91, 2, 33, 1, 85, 3, 36, 79, 18, 92, 5, 34, 81, 98, 40, 38, 68, 90, 70, 89, 65, 48, 6, 77, 30, 72, 62, 16, 83, 32, 54, 99, 82, 75, 41, 53, 17, 67, 43, 28, 21, 46, 7, 25, 64, 13, 14, 87, 58, 63, 31, 39, 47, 24, 71, 74, 55, 20, 11, 22, 45, 44, 51, 37, 15, 42, 56, 66, 29, 86, 49, 69, 57, 73, 50, 60, 0, 4, 19, 52, 97, 12, 26], [88, 86, 41, 1, 70, 10, 19, 2, 11, 44, 87, 26, 53, 59, 40, 18, 61, 13, 21, 56, 85, 75, 25, 5, 97, 7, 36, 67, 76, 79, 90, 65, 91, 0, 98, 89, 20, 55, 93, 58, 28, 63, 6, 83, 47, 71, 73, 49, 39, 31, 48, 69, 82, 50, 78, 62, 14, 74, 29, 54, 57, 80, 32, 94, 3, 66, 30, 35, 8, 46, 16, 51, 24, 17, 4, 84, 45, 60, 34, 15, 72, 77, 42, 12, 64, 9, 33, 95, 81, 96, 38, 43, 52, 99, 22, 92, 27, 23, 37, 68], [90, 93, 83, 21, 96, 71, 67, 28, 37, 75, 55, 58, 56, 39, 16, 46, 91, 41, 77, 92, 99, 65, 27, 5, 24, 1, 69, 7, 31, 35, 33, 64, 12, 14, 45, 11, 98, 0, 57, 72, 74, 13, 61, 40, 63, 89, 53, 85, 18, 76, 2, 70, 20, 60, 84, 52, 25, 43, 54, 17, 36, 19, 97, 73, 94, 62, 3, 23, 34, 88, 29, 80, 50, 22, 81, 87, 6, 30, 78, 48, 79, 44, 66, 8, 51, 86, 4, 15, 42, 10, 82, 32, 68, 26, 38, 47, 49, 9, 95, 59]]];\nconst ibtable2 = [[4, 7, 8, 0, 9, 1, 3, 6, 2, 5], [5, 0, 4, 1, 3, 8, 9, 7, 6, 2], [0, 2, 7, 8, 9, 1, 6, 3, 5, 4], [5, 9, 8, 4, 1, 7, 0, 2, 3, 6], [7, 3, 0, 1, 8, 9, 6, 5, 2, 4], [7, 2, 4, 0, 1, 9, 6, 3, 5, 8], [4, 1, 6, 3, 5, 8, 0, 7, 2, 9], [6, 8, 4, 1, 5, 3, 7, 2, 9, 0], [4, 1, 8, 3, 7, 2, 0, 6, 5, 9], [7, 4, 5, 6, 2, 3, 9, 1, 8, 0]];\n\ntype DecodedAccessCode = { revision: number; serial: number };\n\nfunction crc16(data: BigInteger, bits: number, initial: number = 0xffff, poly: number = 0x8408): number {\n let v = bigInt(initial);\n let bigPoly = bigInt(poly);\n\n for (let i = 0; i < bits; i++) {\n v = v.shiftRight(1).xor(bigPoly.and(v.xor(data).and(bigInt.one).equals(bigInt.one) ? bigPoly : bigInt.zero));\n data = data.shiftRight(1);\n }\n\n return v.toJSNumber();\n}\n\nexport function decodeAccessCode(code: string): DecodedAccessCode | null {\n code = code.replace(/\\D/i, '');\n\n if (code.length !== 20) {\n return null;\n }\n\n let body = _.range(3, 15, 2).map(i => parseInt(code[i]) * 10 + parseInt(code[i + 1]));\n let crc = _.range(15, 20).map(i => parseInt(code[i]));\n\n let boxes = [(crc[3] + crc[2]) % 10, crc[2], crc[3], crc[4], (crc[4] + crc[0]) % 10, crc[1]];\n\n for (const [n, i] of body.entries()) {\n body[n] = ibtable[4][boxes[n]][i];\n }\n\n const rv = body[0] >> 4;\n\n boxes = [(crc[1] + crc[0]) % 10, crc[1], crc[2], crc[3], crc[4], (crc[4] + crc[1]) % 10]\n for (const [n, i] of body.entries()) {\n if (n == 0) {\n body[n] = (body[n] & 0xf0) | ibtable2[boxes[n]][body[n] & 0x0f];\n } else {\n body[n] = ibtable[rv][boxes[n]][i];\n }\n }\n\n const serial = body.map(i => i.toString().padStart(2, '0')).join('')\n\n if (crc16(bigInt(code.substring(0, 3) + serial, 16), 15 * 4) !== parseInt(code.substring(15, 20))) {\n throw new Error(`CRC16 mismatch.`);\n }\n\n return { revision: rv, serial: parseInt(serial) };\n}\n\nexport function encodeAccessCode(company: number, serial: number, rev: number = 0): string {\n if (company < 0 || company > 999) {\n throw new Error(`Invalid company code`);\n }\n\n if (serial < 0 || serial > 99999999999) {\n throw new Error(`Invalid serial number`);\n }\n\n if (rev < 0 || rev > sbtable.length) {\n throw new Error(`Invalid revision`);\n }\n\n const bodyStr = `${rev}${serial.toString().padStart(11, '0')}`;\n const crc_i = crc16(bigInt(company.toString().padStart(3, '0') + bodyStr, 16), 15 * 4);\n\n const crc = _.range(5).map(i => Math.floor(crc_i / (10 ** (4 - i))) % 10);\n const body = _.range(0, 12, 2).map(i => parseInt(bodyStr[i]) * 10 + parseInt(bodyStr[i + 1]));\n\n let boxes = [(crc[1] + crc[0]) % 10, crc[1], crc[2], crc[3], crc[4], (crc[4] + crc[1]) % 10];\n for (const [n, i] of body.entries()) {\n if (n == 0) {\n body[n] = (body[n] & 0xf0) | sbtable2[boxes[n]][body[n] & 0x0f];\n } else {\n body[n] = sbtable[rev][boxes[n]][i];\n }\n }\n\n boxes = [(crc[3] + crc[2]) % 10, crc[2], crc[3], crc[4], (crc[4] + crc[0]) % 10, crc[1]]\n for (const [n, i] of body.entries()) {\n body[n] = sbtable[4][boxes[n]][i];\n }\n\n return `${company.toString().padStart(3, '0')}${body.map(i => i.toString().padStart(2, '0')).join('')}${crc_i.toString().padStart(5, '0')}`;\n}\n","import {encodeAccessCode} from \"./card-encoding\";\n\nexport const CARD_ID_REGEX = /^(?:[0-9]{4} ?){5}$/i;\nexport const AMNET_COMPANY_ID = 597;\n\nexport function generateCardNumber(): string {\n // serial between 0 and 99999999999\n const serial = Math.floor(Math.random() * 100000000000);\n return encodeAccessCode(AMNET_COMPANY_ID, serial, 0);\n}\n\n/**\n * Validates the provided card id by known parameters\n * @param id The card id to validate\n */\nexport function validateCardId(id: string): boolean {\n return id[0] !== '3' && CARD_ID_REGEX.test(id);\n}\n","/**\n * Get the game name from the game identifier (4-letter code)\n * @param id\n */\nexport function getGameName(id: string): string | null {\n switch (id?.toUpperCase()) {\n case \"SDGT\":\n return \"Initial D The Arcade\";\n case \"SDHD\":\n case \"SDBT\":\n return \"CHUNITHM\";\n case \"SDDT\":\n return \"O.N.G.E.K.I.\";\n case \"SDEZ\":\n return \"maimai DX\";\n case \"SBZV\":\n return \"Project DIVA Future Tone\";\n \n default:\n return null;\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;AAGO,IAAM,oBAAoB;AAK1B,IAAM,wBAAwB;AA0CrC,eAAsB,cAAc,QAAgC,SAA0B,QAAuC;AACjI,MAAI,OAAO,aAAa,yBAAyB,OAAO,aAAa,mBAAmB;AACpF,UAAM,IAAI,MAAM,gCAAgC;AAAA,EACpD;AAEA,MAAI;AACA,UAAM,WAAW,MAAM,MAAM,GAAG,IAAI,IAAI,OAAO,aAAa,EAAE,MAAM,iBAAiB;AAAA,MACjF,QAAQ;AAAA,MACR,SAAS;AAAA,QACL,gBAAgB;AAAA,MACpB;AAAA,MACA,MAAM,KAAK,UAAU,OAAO;AAAA,MAC5B;AAAA,IACJ,CAAC;AAED,WAAO,SAAS;AAAA,EACpB,SAAQ;AACJ,WAAO;AAAA,EACX;AACJ;AAOA,eAAsB,gBAAgB,eAAuB,OAAkD;AAC3G,MAAI;AACA,UAAM,WAAW,MAAM,MAAM,GAAG,IAAI,IAAI,aAAa,EAAE,MAAM,eAAe;AAAA,MACxE,QAAQ;AAAA,IACZ,CAAC;AAED,QAAI,CAAC,SAAS,IAAI;AACd,aAAO;AAAA,IACX;AAEA,WAAO,iCACA,MAAM,SAAS,KAAK,IADpB;AAAA,MAEH;AAAA,IACJ;AAAA,EACJ,SAAQ;AACJ,WAAO;AAAA,EACX;AACJ;;;AC7FA,OAAO,OAAO;AACd,OAAO,YAA0B;AAEjC,IAAM,UAAU,CAAC,CAAC,CAAC,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,GAAG,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,EAAE,GAAG,CAAC,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,EAAE,GAAG,CAAC,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,EAAE,GAAG,CAAC,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,GAAG,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,EAAE,GAAG,CAAC,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,GAAG,IAAI,IAAI,IAAI,IAAI,GAAG,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,EAAE,GAAG,CAAC,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,EAAE,GAAG,CAAC,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,GAAG,IAAI,GAAG,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,EAAE,GAAG,CAAC,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,GAAG,GAAG,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,CAAC,GAAG,CAAC,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,GAAG,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,GAAG,IAAI,GAAG,IAAI,IAAI,CAAC,GAAG,CAAC,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,GAAG,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,EAAE,GAAG,CAAC,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,GAAG,GAAG,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,CAAC,GAAG,CAAC,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,EAAE,GAAG,CAAC,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,GAAG,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,EAAE,GAAG,CAAC,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,GAAG,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,EAAE,GAAG,CAAC,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,CAAC,GAAG,CAAC,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,GAAG,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,EAAE,GAAG,CAAC,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,GAAG,IAAI,IAAI,GAAG,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,GAAG,EAAE,GAAG,CAAC,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,EAAE,GAAG,CAAC,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,EAAE,CAAC,GAAG,CAAC,CAAC,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,EAAE,GAAG,CAAC,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,EAAE,GAAG,CAAC,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,GAAG,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,EAAE,GAAG,CAAC,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,GAAG,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,EAAE,GAAG,CAAC,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,GAAG,IAAI,GAAG,GAAG,IAAI,IAAI,IAAI,EAAE,GAAG,CAAC,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,EAAE,GAAG,CAAC,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,EAAE,GAAG,CAAC,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,GAAG,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,GAAG,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,EAAE,GAAG,CAAC,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,EAAE,CAAC,GAAG,CAAC,CAAC,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,EAAE,GAAG,CAAC,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,GAAG,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,GAAG,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,EAAE,GAAG,CAAC,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,GAAG,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,GAAG,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,EAAE,GAAG,CAAC,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,EAAE,GAAG,CAAC,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,GAAG,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,EAAE,GAAG,CAAC,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,EAAE,GAAG,CAAC,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,GAAG,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,EAAE,GAAG,CAAC,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,EAAE,GAAG,CAAC,GAAG,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,GAAG,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,GAAG,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,EAAE,GAAG,CAAC,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,EAAE,CAAC,GAAG,CAAC,CAAC,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,EAAE,GAAG,CAAC,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,EAAE,GAAG,CAAC,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,EAAE,GAAG,CAAC,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,GAAG,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,CAAC,GAAG,CAAC,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,GAAG,IAAI,IAAI,IAAI,IAAI,GAAG,GAAG,IAAI,GAAG,IAAI,IAAI,GAAG,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,EAAE,GAAG,CAAC,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,GAAG,IAAI,IAAI,GAAG,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,EAAE,GAAG,CAAC,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,GAAG,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,EAAE,GAAG,CAAC,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,GAAG,IAAI,IAAI,EAAE,GAAG,CAAC,IAAI,GAAG,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,EAAE,GAAG,CAAC,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,GAAG,IAAI,IAAI,GAAG,IAAI,IAAI,EAAE,CAAC,CAAC;AACzqmB,IAAM,WAAW,CAAC,CAAC,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC,GAAG,CAAC,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC,GAAG,CAAC,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC,GAAG,CAAC,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC,GAAG,CAAC,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC,GAAG,CAAC,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC,GAAG,CAAC,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC,GAAG,CAAC,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC,GAAG,CAAC,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC,GAAG,CAAC,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC,CAAC;AAEhV,IAAM,UAAU,CAAC,CAAC,CAAC,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,GAAG,GAAG,IAAI,IAAI,IAAI,IAAI,GAAG,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,CAAC,GAAG,CAAC,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,GAAG,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,EAAE,GAAG,CAAC,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,GAAG,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,EAAE,GAAG,CAAC,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,EAAE,GAAG,CAAC,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,GAAG,GAAG,IAAI,GAAG,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,EAAE,GAAG,CAAC,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,GAAG,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,EAAE,GAAG,CAAC,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,EAAE,GAAG,CAAC,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,EAAE,GAAG,CAAC,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,EAAE,GAAG,CAAC,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,EAAE,CAAC,GAAG,CAAC,CAAC,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,EAAE,GAAG,CAAC,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,GAAG,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,EAAE,GAAG,CAAC,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,GAAG,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,EAAE,GAAG,CAAC,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,GAAG,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,EAAE,GAAG,CAAC,IAAI,IAAI,IAAI,GAAG,IAAI,GAAG,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,GAAG,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,EAAE,GAAG,CAAC,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,GAAG,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,EAAE,GAAG,CAAC,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,EAAE,GAAG,CAAC,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,GAAG,GAAG,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,EAAE,GAAG,CAAC,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,GAAG,GAAG,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,EAAE,GAAG,CAAC,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,EAAE,CAAC,GAAG,CAAC,CAAC,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,GAAG,GAAG,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,GAAG,IAAI,EAAE,GAAG,CAAC,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,GAAG,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,EAAE,GAAG,CAAC,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,EAAE,GAAG,CAAC,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,EAAE,GAAG,CAAC,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,GAAG,IAAI,IAAI,IAAI,IAAI,GAAG,EAAE,GAAG,CAAC,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,GAAG,IAAI,GAAG,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,EAAE,GAAG,CAAC,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,GAAG,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,EAAE,GAAG,CAAC,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,GAAG,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,GAAG,IAAI,GAAG,IAAI,IAAI,IAAI,EAAE,GAAG,CAAC,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,GAAG,GAAG,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,GAAG,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,EAAE,GAAG,CAAC,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,EAAE,CAAC,GAAG,CAAC,CAAC,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,GAAG,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,CAAC,GAAG,CAAC,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,GAAG,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,GAAG,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,GAAG,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,EAAE,GAAG,CAAC,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,GAAG,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,GAAG,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,GAAG,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,EAAE,GAAG,CAAC,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,GAAG,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,EAAE,GAAG,CAAC,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,GAAG,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,EAAE,GAAG,CAAC,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,GAAG,GAAG,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,EAAE,GAAG,CAAC,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,GAAG,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,EAAE,GAAG,CAAC,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,CAAC,GAAG,CAAC,GAAG,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,GAAG,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,EAAE,GAAG,CAAC,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,GAAG,IAAI,IAAI,IAAI,IAAI,EAAE,CAAC,GAAG,CAAC,CAAC,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,CAAC,GAAG,CAAC,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,EAAE,GAAG,CAAC,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,GAAG,EAAE,GAAG,CAAC,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,GAAG,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,EAAE,GAAG,CAAC,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,GAAG,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,GAAG,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,EAAE,GAAG,CAAC,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,GAAG,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,EAAE,GAAG,CAAC,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,GAAG,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,GAAG,IAAI,EAAE,GAAG,CAAC,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,GAAG,IAAI,IAAI,IAAI,IAAI,EAAE,GAAG,CAAC,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,EAAE,GAAG,CAAC,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,EAAE,CAAC,CAAC;AACzqmB,IAAM,WAAW,CAAC,CAAC,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC,GAAG,CAAC,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC,GAAG,CAAC,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC,GAAG,CAAC,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC,GAAG,CAAC,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC,GAAG,CAAC,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC,GAAG,CAAC,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC,GAAG,CAAC,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC,GAAG,CAAC,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC,GAAG,CAAC,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC,CAAC;AAIhV,SAAS,MAAM,MAAkB,MAAc,UAAkB,OAAQ,OAAe,OAAgB;AACpG,MAAI,IAAI,OAAO,OAAO;AACtB,MAAI,UAAU,OAAO,IAAI;AAEzB,WAAS,IAAI,GAAG,IAAI,MAAM,KAAK;AAC3B,QAAI,EAAE,WAAW,CAAC,EAAE,IAAI,QAAQ,IAAI,EAAE,IAAI,IAAI,EAAE,IAAI,OAAO,GAAG,EAAE,OAAO,OAAO,GAAG,IAAI,UAAU,OAAO,IAAI,CAAC;AAC3G,WAAO,KAAK,WAAW,CAAC;AAAA,EAC5B;AAEA,SAAO,EAAE,WAAW;AACxB;AAEO,SAAS,iBAAiB,MAAwC;AACrE,SAAO,KAAK,QAAQ,OAAO,EAAE;AAE7B,MAAI,KAAK,WAAW,IAAI;AACpB,WAAO;AAAA,EACX;AAEA,MAAI,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC,EAAE,IAAI,OAAK,SAAS,KAAK,CAAC,CAAC,IAAI,KAAK,SAAS,KAAK,IAAI,CAAC,CAAC,CAAC;AACpF,MAAI,MAAM,EAAE,MAAM,IAAI,EAAE,EAAE,IAAI,OAAK,SAAS,KAAK,CAAC,CAAC,CAAC;AAEpD,MAAI,QAAQ,EAAE,IAAI,CAAC,IAAI,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,GAAG,IAAI,CAAC,GAAG,IAAI,CAAC,IAAI,IAAI,CAAC,IAAI,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,CAAC;AAE3F,aAAW,CAAC,GAAG,CAAC,KAAK,KAAK,QAAQ,GAAG;AACjC,SAAK,CAAC,IAAI,QAAQ,CAAC,EAAE,MAAM,CAAC,CAAC,EAAE,CAAC;AAAA,EACpC;AAEA,QAAM,KAAK,KAAK,CAAC,KAAK;AAEtB,UAAQ,EAAE,IAAI,CAAC,IAAI,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,GAAG,IAAI,CAAC,GAAG,IAAI,CAAC,GAAG,IAAI,CAAC,IAAI,IAAI,CAAC,IAAI,IAAI,CAAC,KAAK,EAAE;AACvF,aAAW,CAAC,GAAG,CAAC,KAAK,KAAK,QAAQ,GAAG;AACjC,QAAI,KAAK,GAAG;AACR,WAAK,CAAC,IAAK,KAAK,CAAC,IAAI,MAAQ,SAAS,MAAM,CAAC,CAAC,EAAE,KAAK,CAAC,IAAI,EAAI;AAAA,IAClE,OAAO;AACH,WAAK,CAAC,IAAI,QAAQ,EAAE,EAAE,MAAM,CAAC,CAAC,EAAE,CAAC;AAAA,IACrC;AAAA,EACJ;AAEA,QAAM,SAAS,KAAK,IAAI,OAAK,EAAE,SAAS,EAAE,SAAS,GAAG,GAAG,CAAC,EAAE,KAAK,EAAE;AAEnE,MAAI,MAAM,OAAO,KAAK,UAAU,GAAG,CAAC,IAAI,QAAQ,EAAE,GAAG,KAAK,CAAC,MAAM,SAAS,KAAK,UAAU,IAAI,EAAE,CAAC,GAAG;AAC/F,UAAM,IAAI,MAAM,iBAAiB;AAAA,EACrC;AAEA,SAAO,EAAE,UAAU,IAAI,QAAQ,SAAS,MAAM,EAAE;AACpD;AAEO,SAAS,iBAAiB,SAAiB,QAAgB,MAAc,GAAW;AACvF,MAAI,UAAU,KAAK,UAAU,KAAK;AAC9B,UAAM,IAAI,MAAM,sBAAsB;AAAA,EAC1C;AAEA,MAAI,SAAS,KAAK,SAAS,aAAa;AACpC,UAAM,IAAI,MAAM,uBAAuB;AAAA,EAC3C;AAEA,MAAI,MAAM,KAAK,MAAM,QAAQ,QAAQ;AACjC,UAAM,IAAI,MAAM,kBAAkB;AAAA,EACtC;AAEA,QAAM,UAAU,GAAG,GAAG,GAAG,OAAO,SAAS,EAAE,SAAS,IAAI,GAAG,CAAC;AAC5D,QAAM,QAAQ,MAAM,OAAO,QAAQ,SAAS,EAAE,SAAS,GAAG,GAAG,IAAI,SAAS,EAAE,GAAG,KAAK,CAAC;AAErF,QAAM,MAAM,EAAE,MAAM,CAAC,EAAE,IAAI,OAAK,KAAK,MAAM,QAAS,OAAO,IAAI,EAAG,IAAI,EAAE;AACxE,QAAM,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC,EAAE,IAAI,OAAK,SAAS,QAAQ,CAAC,CAAC,IAAI,KAAK,SAAS,QAAQ,IAAI,CAAC,CAAC,CAAC;AAE5F,MAAI,QAAQ,EAAE,IAAI,CAAC,IAAI,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,GAAG,IAAI,CAAC,GAAG,IAAI,CAAC,GAAG,IAAI,CAAC,IAAI,IAAI,CAAC,IAAI,IAAI,CAAC,KAAK,EAAE;AAC3F,aAAW,CAAC,GAAG,CAAC,KAAK,KAAK,QAAQ,GAAG;AACjC,QAAI,KAAK,GAAG;AACR,WAAK,CAAC,IAAK,KAAK,CAAC,IAAI,MAAQ,SAAS,MAAM,CAAC,CAAC,EAAE,KAAK,CAAC,IAAI,EAAI;AAAA,IAClE,OAAO;AACH,WAAK,CAAC,IAAI,QAAQ,GAAG,EAAE,MAAM,CAAC,CAAC,EAAE,CAAC;AAAA,IACtC;AAAA,EACJ;AAEA,UAAQ,EAAE,IAAI,CAAC,IAAI,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,GAAG,IAAI,CAAC,GAAG,IAAI,CAAC,IAAI,IAAI,CAAC,IAAI,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,CAAC;AACvF,aAAW,CAAC,GAAG,CAAC,KAAK,KAAK,QAAQ,GAAG;AACjC,SAAK,CAAC,IAAI,QAAQ,CAAC,EAAE,MAAM,CAAC,CAAC,EAAE,CAAC;AAAA,EACpC;AAEA,SAAO,GAAG,QAAQ,SAAS,EAAE,SAAS,GAAG,GAAG,CAAC,GAAG,KAAK,IAAI,OAAK,EAAE,SAAS,EAAE,SAAS,GAAG,GAAG,CAAC,EAAE,KAAK,EAAE,CAAC,GAAG,MAAM,SAAS,EAAE,SAAS,GAAG,GAAG,CAAC;AAC7I;;;AC3FO,IAAM,gBAAgB;AACtB,IAAM,mBAAmB;AAEzB,SAAS,qBAA6B;AAEzC,QAAM,SAAS,KAAK,MAAM,KAAK,OAAO,IAAI,IAAY;AACtD,SAAO,iBAAiB,kBAAkB,QAAQ,CAAC;AACvD;AAMO,SAAS,eAAe,IAAqB;AAChD,SAAO,GAAG,CAAC,MAAM,OAAO,cAAc,KAAK,EAAE;AACjD;;;ACbO,SAAS,YAAY,IAA2B;AACnD,UAAQ,yBAAI,eAAe;AAAA,IACvB,KAAK;AACD,aAAO;AAAA,IACX,KAAK;AAAA,IACL,KAAK;AACD,aAAO;AAAA,IACX,KAAK;AACD,aAAO;AAAA,IACX,KAAK;AACD,aAAO;AAAA,IACX,KAAK;AACD,aAAO;AAAA,IAEX;AACI,aAAO;AAAA,EACf;AACJ;","names":[]} \ No newline at end of file diff --git a/amnet-shared/package-lock.json b/amnet-shared/package-lock.json index 8e7e60e..525862c 100644 --- a/amnet-shared/package-lock.json +++ b/amnet-shared/package-lock.json @@ -7,7 +7,12 @@ "": { "name": "amnet-shared", "version": "1.0.0", + "dependencies": { + "big-integer": "^1.6.52", + "lodash": "^4.17.21" + }, "devDependencies": { + "@types/lodash": "^4.17.14", "tsup": "^8.2.4", "typescript": "^5.5.4" } @@ -771,6 +776,13 @@ "dev": true, "license": "MIT" }, + "node_modules/@types/lodash": { + "version": "4.17.14", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.14.tgz", + "integrity": "sha512-jsxagdikDiDBeIRaPYtArcT8my4tN1og7MtMRquFT3XNA6axxyHDRUemqDz/taRDdOUn0GnGHRCuff4q48sW9A==", + "dev": true, + "license": "MIT" + }, "node_modules/ansi-regex": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", @@ -835,6 +847,15 @@ "dev": true, "license": "MIT" }, + "node_modules/big-integer": { + "version": "1.6.52", + "resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.52.tgz", + "integrity": "sha512-QxD8cf2eVqJOOz63z6JIN9BzvVs/dlySa5HGSBH5xtR8dPteIRQnBxxKqkNTiT6jbDTF6jAfrd4oMcND9RGbQg==", + "license": "Unlicense", + "engines": { + "node": ">=0.6" + } + }, "node_modules/binary-extensions": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", @@ -963,9 +984,9 @@ } }, "node_modules/cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", "dev": true, "license": "MIT", "dependencies": { @@ -1391,6 +1412,12 @@ "node": "^12.20.0 || ^14.13.1 || >=16.0.0" } }, + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "license": "MIT" + }, "node_modules/lodash.sortby": { "version": "4.7.0", "resolved": "https://registry.npmjs.org/lodash.sortby/-/lodash.sortby-4.7.0.tgz", diff --git a/amnet-shared/package.json b/amnet-shared/package.json index a3b58fe..0b0bdcc 100644 --- a/amnet-shared/package.json +++ b/amnet-shared/package.json @@ -16,7 +16,12 @@ ".": "./dist/index.mjs" }, "devDependencies": { + "@types/lodash": "^4.17.14", "tsup": "^8.2.4", "typescript": "^5.5.4" + }, + "dependencies": { + "big-integer": "^1.6.52", + "lodash": "^4.17.21" } } diff --git a/amnet-shared/src/api.ts b/amnet-shared/src/api.ts index 1b90f75..5a2a64e 100644 --- a/amnet-shared/src/api.ts +++ b/amnet-shared/src/api.ts @@ -10,6 +10,7 @@ export const MIN_AMNET_API_VERSION = 1; export interface AMCardInRequest { cardId: string; + physicalCardIDm?: string; } /** @@ -51,7 +52,7 @@ export async function performCardIn(server: AMServerConnectionInfo, request: AMC if (server.apiVersion < MIN_AMNET_API_VERSION || server.apiVersion > AMNET_API_VERSION) { throw new Error("Unsupported server API version"); } - + try { const response = await fetch(`${new URL(server.serverAddress).origin}/amnet/signin`, { method: "POST", @@ -78,7 +79,7 @@ export async function fetchServerInfo(serverAddress: string, abort: AbortSignal) const response = await fetch(`${new URL(serverAddress).origin}/amnet/info`, { signal: abort }); - + if (!response.ok) { return null; } diff --git a/amnet-shared/src/card-encoding.ts b/amnet-shared/src/card-encoding.ts new file mode 100644 index 0000000..2802109 --- /dev/null +++ b/amnet-shared/src/card-encoding.ts @@ -0,0 +1,94 @@ +import _ from "lodash"; +import bigInt, {BigInteger} from "big-integer"; + +const sbtable = [[[45, 50, 94, 2, 66, 55, 56, 49, 99, 36, 60, 0, 73, 30, 39, 37, 80, 74, 85, 7, 12, 33, 93, 83, 95, 91, 98, 92, 23, 24, 79, 21, 31, 35, 71, 70, 4, 43, 1, 5, 88, 90, 69, 58, 76, 20, 84, 62, 77, 44, 61, 11, 16, 53, 82, 34, 13, 47, 48, 87, 89, 15, 64, 3, 54, 28, 57, 67, 9, 75, 32, 65, 96, 17, 18, 29, 10, 14, 42, 6, 46, 26, 40, 59, 63, 78, 68, 8, 86, 51, 25, 72, 38, 97, 19, 81, 27, 41, 52, 22], [26, 32, 34, 79, 42, 45, 4, 75, 22, 73, 64, 98, 49, 19, 5, 24, 6, 55, 63, 25, 40, 77, 54, 12, 9, 44, 83, 71, 0, 90, 97, 96, 81, 80, 3, 31, 56, 92, 17, 86, 72, 28, 36, 78, 62, 30, 7, 46, 87, 20, 82, 50, 35, 61, 41, 94, 68, 11, 1, 10, 74, 67, 85, 43, 57, 15, 95, 84, 65, 53, 69, 52, 76, 88, 2, 14, 37, 58, 93, 16, 59, 51, 18, 99, 39, 47, 89, 8, 13, 91, 38, 33, 70, 48, 23, 29, 27, 66, 60, 21], [28, 53, 30, 85, 0, 95, 70, 47, 40, 51, 94, 68, 99, 15, 5, 57, 1, 16, 80, 93, 91, 52, 2, 32, 48, 77, 41, 75, 22, 39, 50, 81, 79, 73, 97, 76, 60, 4, 59, 25, 78, 38, 46, 58, 90, 84, 56, 6, 83, 62, 42, 10, 64, 31, 36, 61, 65, 63, 18, 8, 9, 96, 55, 26, 89, 67, 3, 98, 35, 21, 13, 12, 88, 71, 37, 29, 87, 49, 24, 86, 92, 20, 44, 74, 69, 17, 82, 54, 27, 7, 23, 66, 11, 19, 34, 45, 14, 72, 43, 33], [32, 44, 86, 79, 38, 61, 25, 8, 5, 85, 78, 48, 33, 87, 84, 35, 64, 41, 60, 21, 96, 75, 6, 69, 39, 94, 3, 92, 37, 77, 15, 13, 29, 59, 76, 91, 65, 56, 73, 83, 27, 62, 89, 50, 18, 98, 81, 17, 71, 28, 82, 11, 30, 43, 34, 20, 70, 22, 46, 63, 52, 68, 90, 53, 36, 10, 74, 58, 40, 88, 9, 2, 42, 26, 24, 4, 95, 57, 31, 66, 0, 14, 49, 16, 99, 19, 51, 23, 47, 12, 93, 1, 7, 80, 45, 97, 55, 67, 72, 54], [58, 35, 42, 38, 63, 36, 68, 30, 81, 4, 87, 80, 32, 69, 37, 67, 1, 86, 61, 94, 27, 11, 84, 26, 59, 73, 53, 66, 72, 71, 39, 33, 99, 8, 43, 88, 17, 22, 89, 5, 46, 93, 98, 48, 55, 83, 34, 3, 0, 16, 12, 20, 78, 9, 2, 76, 54, 51, 25, 24, 62, 57, 92, 10, 50, 28, 79, 23, 52, 95, 44, 60, 74, 90, 19, 77, 21, 31, 96, 49, 64, 6, 29, 85, 18, 13, 82, 47, 56, 45, 15, 7, 97, 75, 40, 41, 65, 14, 70, 91], [81, 82, 66, 72, 83, 4, 20, 94, 53, 48, 77, 41, 67, 64, 9, 24, 36, 55, 14, 1, 78, 84, 49, 0, 44, 58, 70, 25, 28, 73, 8, 68, 88, 54, 86, 87, 23, 52, 27, 5, 97, 37, 62, 50, 3, 89, 92, 47, 30, 10, 29, 80, 22, 26, 11, 13, 69, 60, 38, 90, 85, 57, 12, 75, 46, 39, 74, 33, 42, 93, 98, 91, 59, 99, 18, 6, 17, 16, 32, 40, 63, 7, 76, 15, 43, 71, 51, 35, 2, 65, 34, 96, 19, 56, 79, 21, 95, 45, 61, 31], [25, 88, 7, 57, 98, 63, 86, 13, 69, 84, 56, 20, 68, 90, 35, 6, 43, 93, 95, 3, 75, 4, 9, 28, 31, 66, 21, 44, 30, 76, 11, 22, 49, 2, 77, 40, 85, 19, 82, 16, 97, 92, 39, 96, 18, 32, 42, 94, 70, 71, 54, 79, 67, 78, 37, 12, 99, 53, 61, 41, 87, 17, 1, 14, 52, 10, 47, 58, 27, 46, 36, 55, 26, 15, 33, 50, 72, 51, 89, 23, 74, 59, 64, 8, 83, 65, 80, 29, 38, 0, 60, 24, 45, 81, 48, 91, 73, 5, 34, 62], [73, 85, 37, 11, 80, 46, 16, 47, 88, 65, 94, 64, 12, 38, 98, 70, 95, 48, 92, 18, 56, 75, 58, 7, 81, 15, 74, 13, 5, 44, 27, 32, 76, 90, 33, 55, 26, 96, 77, 24, 0, 89, 8, 4, 28, 39, 71, 3, 10, 41, 91, 53, 31, 68, 36, 17, 69, 60, 34, 54, 93, 82, 21, 51, 87, 59, 61, 6, 1, 23, 30, 66, 43, 25, 35, 42, 49, 78, 62, 14, 19, 20, 29, 22, 52, 83, 63, 45, 2, 99, 50, 79, 72, 40, 84, 97, 86, 57, 67, 9], [48, 94, 17, 55, 59, 24, 72, 75, 38, 85, 34, 98, 95, 36, 49, 63, 57, 54, 29, 6, 52, 47, 73, 1, 82, 9, 66, 83, 31, 61, 78, 60, 97, 14, 87, 15, 90, 70, 53, 10, 27, 8, 3, 64, 51, 50, 68, 26, 22, 19, 42, 96, 67, 7, 25, 39, 92, 30, 58, 93, 21, 74, 41, 18, 65, 44, 88, 32, 71, 69, 12, 77, 13, 11, 99, 79, 37, 89, 81, 35, 86, 56, 45, 76, 46, 80, 62, 43, 16, 84, 40, 5, 33, 91, 4, 20, 0, 23, 28, 2], [61, 45, 79, 13, 59, 52, 6, 77, 3, 31, 70, 80, 26, 33, 36, 4, 27, 32, 24, 74, 29, 94, 16, 12, 76, 7, 88, 57, 78, 42, 97, 96, 43, 83, 92, 21, 51, 47, 49, 58, 90, 41, 93, 98, 35, 63, 86, 37, 5, 30, 28, 72, 25, 22, 60, 19, 39, 34, 68, 50, 8, 64, 46, 99, 84, 87, 69, 56, 53, 55, 44, 54, 89, 65, 85, 0, 71, 15, 17, 66, 81, 82, 91, 95, 62, 48, 38, 75, 40, 14, 9, 10, 73, 67, 18, 11, 23, 2, 20, 1]], [[95, 90, 61, 38, 18, 7, 83, 39, 79, 14, 48, 21, 81, 44, 78, 50, 56, 91, 12, 86, 99, 98, 43, 63, 73, 87, 42, 72, 15, 68, 97, 23, 88, 69, 2, 51, 19, 58, 59, 22, 20, 29, 82, 11, 75, 70, 9, 71, 27, 30, 47, 89, 92, 60, 46, 76, 93, 54, 1, 96, 94, 57, 40, 62, 41, 3, 28, 64, 37, 74, 67, 16, 65, 53, 5, 36, 24, 45, 32, 33, 10, 85, 26, 4, 84, 77, 35, 13, 6, 8, 17, 80, 25, 55, 52, 66, 49, 34, 0, 31], [18, 14, 70, 43, 74, 45, 94, 36, 40, 6, 31, 46, 15, 47, 13, 19, 72, 61, 99, 21, 17, 92, 88, 78, 73, 90, 0, 96, 20, 28, 25, 51, 50, 77, 29, 16, 54, 12, 58, 38, 71, 23, 42, 83, 65, 60, 10, 33, 22, 76, 95, 32, 57, 5, 59, 67, 68, 3, 91, 85, 26, 62, 41, 1, 53, 82, 34, 24, 87, 27, 89, 75, 56, 30, 81, 7, 8, 4, 64, 66, 9, 63, 35, 52, 80, 93, 69, 84, 55, 86, 48, 98, 79, 97, 49, 44, 39, 11, 37, 2], [76, 16, 73, 29, 34, 14, 36, 90, 58, 70, 46, 2, 91, 59, 63, 32, 84, 40, 78, 38, 19, 37, 0, 31, 8, 44, 94, 39, 10, 66, 42, 1, 21, 88, 82, 97, 33, 4, 99, 74, 89, 62, 25, 87, 77, 43, 50, 95, 64, 23, 47, 93, 65, 27, 12, 71, 9, 72, 60, 18, 7, 22, 79, 24, 96, 45, 49, 98, 57, 11, 5, 86, 3, 80, 26, 51, 17, 85, 54, 67, 48, 35, 53, 41, 28, 13, 20, 92, 83, 69, 6, 68, 75, 52, 61, 30, 81, 56, 15, 55], [0, 62, 25, 61, 56, 87, 54, 27, 75, 49, 18, 69, 17, 71, 40, 6, 90, 80, 23, 26, 68, 24, 10, 21, 47, 88, 36, 55, 15, 22, 48, 12, 83, 99, 46, 67, 59, 29, 58, 73, 78, 97, 19, 33, 51, 98, 65, 91, 16, 4, 63, 41, 3, 70, 30, 8, 89, 34, 72, 60, 9, 95, 50, 2, 66, 53, 44, 85, 28, 5, 92, 43, 64, 96, 74, 77, 45, 52, 14, 42, 1, 32, 20, 76, 86, 82, 94, 7, 39, 13, 31, 11, 84, 93, 35, 37, 38, 57, 79, 81], [78, 8, 59, 25, 69, 15, 63, 3, 57, 5, 50, 96, 41, 66, 80, 81, 7, 45, 60, 74, 79, 32, 27, 58, 56, 82, 11, 47, 17, 85, 53, 40, 95, 84, 76, 92, 18, 71, 64, 51, 67, 91, 22, 34, 65, 31, 73, 93, 68, 75, 77, 37, 43, 12, 20, 99, 2, 1, 19, 35, 44, 55, 90, 9, 0, 6, 33, 89, 24, 14, 97, 10, 48, 61, 23, 54, 98, 86, 88, 94, 46, 70, 28, 36, 16, 30, 4, 39, 26, 38, 87, 52, 83, 49, 62, 42, 72, 29, 13, 21], [20, 88, 35, 5, 85, 98, 11, 78, 62, 83, 79, 80, 40, 14, 91, 8, 7, 69, 71, 61, 49, 38, 64, 82, 0, 47, 84, 95, 2, 50, 77, 41, 97, 36, 33, 81, 46, 21, 73, 48, 31, 92, 54, 89, 87, 60, 90, 10, 76, 45, 99, 52, 3, 44, 39, 43, 18, 16, 63, 12, 28, 70, 86, 6, 4, 24, 59, 30, 96, 65, 22, 56, 74, 23, 32, 75, 53, 93, 15, 67, 66, 17, 29, 25, 42, 37, 57, 9, 72, 68, 26, 34, 27, 51, 19, 58, 55, 94, 13, 1], [72, 53, 79, 61, 30, 33, 25, 75, 8, 55, 14, 6, 22, 93, 18, 77, 4, 74, 44, 36, 82, 94, 2, 5, 62, 54, 28, 3, 63, 97, 65, 7, 84, 73, 39, 92, 67, 91, 24, 45, 15, 81, 19, 78, 80, 64, 34, 43, 32, 87, 52, 95, 89, 37, 10, 23, 20, 68, 42, 47, 59, 58, 49, 71, 40, 85, 13, 31, 12, 57, 96, 90, 56, 41, 48, 9, 99, 35, 98, 26, 1, 46, 11, 69, 27, 83, 60, 50, 21, 70, 0, 88, 29, 86, 76, 16, 66, 38, 51, 17], [3, 68, 86, 94, 81, 90, 85, 32, 65, 52, 50, 42, 80, 78, 26, 93, 57, 58, 69, 82, 92, 27, 11, 67, 95, 41, 21, 88, 35, 17, 19, 15, 22, 62, 40, 76, 63, 59, 37, 55, 75, 9, 24, 89, 56, 53, 23, 60, 25, 6, 1, 71, 16, 7, 10, 44, 8, 12, 87, 64, 54, 72, 20, 33, 70, 79, 14, 97, 4, 99, 45, 39, 2, 77, 98, 74, 49, 30, 13, 61, 66, 73, 47, 43, 96, 83, 18, 91, 28, 48, 38, 34, 31, 36, 29, 0, 84, 46, 5, 51], [71, 84, 25, 70, 77, 56, 61, 47, 72, 27, 54, 89, 9, 46, 95, 59, 42, 98, 63, 69, 48, 16, 97, 14, 66, 83, 87, 68, 17, 2, 15, 79, 31, 1, 57, 12, 33, 36, 0, 40, 21, 50, 76, 41, 10, 13, 44, 5, 53, 4, 38, 35, 55, 96, 81, 91, 90, 64, 34, 51, 6, 28, 32, 39, 75, 18, 93, 24, 78, 7, 52, 43, 49, 37, 74, 8, 58, 65, 92, 67, 85, 20, 94, 88, 80, 86, 19, 60, 3, 11, 30, 45, 29, 22, 26, 73, 99, 23, 62, 82], [67, 91, 46, 33, 76, 3, 96, 23, 9, 68, 49, 63, 1, 92, 58, 62, 69, 77, 70, 75, 71, 94, 51, 55, 50, 52, 0, 88, 18, 16, 73, 6, 12, 87, 93, 79, 84, 57, 48, 41, 20, 47, 15, 42, 54, 81, 7, 30, 34, 56, 29, 8, 98, 5, 45, 64, 83, 74, 22, 82, 80, 95, 2, 72, 44, 31, 86, 78, 13, 10, 28, 89, 60, 35, 61, 19, 14, 85, 4, 43, 11, 40, 26, 99, 39, 32, 90, 17, 24, 37, 36, 21, 25, 53, 97, 59, 27, 38, 65, 66]], [[40, 77, 66, 65, 97, 96, 58, 64, 69, 30, 0, 3, 17, 33, 51, 23, 59, 10, 7, 20, 29, 49, 71, 13, 46, 4, 79, 92, 47, 18, 72, 57, 73, 80, 56, 28, 78, 67, 9, 87, 43, 31, 22, 62, 75, 99, 19, 63, 35, 93, 12, 98, 25, 26, 37, 89, 86, 15, 55, 50, 91, 38, 42, 81, 2, 94, 70, 68, 45, 88, 76, 74, 11, 24, 41, 60, 85, 21, 44, 32, 82, 61, 52, 83, 53, 36, 48, 1, 95, 27, 14, 84, 54, 6, 39, 34, 90, 5, 16, 8], [44, 69, 53, 28, 18, 11, 23, 65, 96, 25, 93, 42, 72, 58, 95, 56, 32, 21, 78, 77, 51, 34, 47, 7, 66, 13, 88, 67, 92, 98, 10, 50, 90, 45, 49, 9, 99, 94, 22, 24, 5, 85, 33, 3, 73, 35, 52, 63, 2, 76, 87, 43, 81, 83, 55, 61, 70, 75, 16, 14, 8, 71, 57, 40, 86, 39, 80, 79, 26, 48, 59, 4, 82, 0, 36, 12, 54, 38, 64, 17, 91, 27, 62, 84, 37, 74, 68, 1, 6, 19, 29, 46, 60, 30, 89, 15, 20, 97, 41, 31], [53, 22, 34, 16, 72, 71, 14, 94, 12, 59, 39, 6, 38, 68, 21, 93, 32, 46, 69, 55, 10, 8, 75, 60, 9, 13, 99, 90, 63, 49, 28, 92, 41, 7, 54, 83, 27, 91, 47, 43, 31, 74, 42, 40, 18, 81, 76, 84, 78, 52, 1, 26, 51, 2, 58, 11, 65, 67, 15, 23, 0, 79, 96, 4, 29, 62, 89, 66, 50, 98, 56, 61, 30, 88, 35, 25, 77, 70, 3, 44, 95, 80, 19, 64, 57, 37, 82, 85, 73, 48, 5, 86, 24, 36, 33, 97, 20, 45, 17, 87], [95, 36, 70, 82, 23, 55, 13, 51, 83, 38, 40, 18, 84, 74, 56, 85, 58, 14, 19, 69, 34, 59, 97, 89, 52, 77, 9, 91, 68, 16, 27, 88, 6, 73, 43, 5, 10, 66, 4, 61, 44, 46, 72, 50, 96, 21, 33, 15, 32, 0, 63, 92, 24, 39, 29, 49, 30, 64, 12, 26, 67, 53, 37, 2, 47, 65, 3, 20, 75, 78, 99, 87, 98, 1, 81, 90, 62, 54, 22, 35, 45, 25, 86, 48, 17, 60, 94, 8, 42, 31, 76, 28, 11, 57, 93, 41, 7, 71, 80, 79], [60, 24, 69, 92, 15, 36, 11, 98, 93, 27, 51, 35, 89, 74, 87, 4, 81, 94, 23, 84, 56, 3, 42, 18, 75, 73, 46, 86, 55, 99, 0, 88, 1, 26, 76, 70, 65, 67, 20, 13, 7, 45, 77, 17, 9, 78, 54, 48, 32, 40, 47, 31, 2, 6, 90, 10, 8, 50, 52, 38, 91, 14, 53, 12, 85, 44, 21, 80, 68, 33, 30, 57, 61, 63, 79, 41, 29, 39, 58, 5, 62, 96, 28, 71, 82, 34, 25, 43, 22, 95, 72, 37, 64, 16, 97, 59, 66, 83, 49, 19], [80, 0, 40, 36, 68, 18, 67, 14, 20, 21, 10, 17, 43, 3, 98, 81, 94, 55, 1, 39, 72, 51, 41, 66, 58, 2, 61, 78, 15, 99, 57, 52, 25, 87, 12, 65, 74, 64, 34, 37, 44, 30, 88, 79, 33, 27, 56, 35, 73, 42, 29, 54, 24, 5, 53, 16, 31, 4, 19, 84, 59, 50, 26, 63, 48, 28, 60, 45, 92, 82, 49, 77, 97, 76, 22, 86, 47, 62, 83, 70, 93, 38, 11, 13, 89, 75, 85, 69, 9, 46, 96, 90, 6, 91, 8, 7, 32, 71, 95, 23], [32, 14, 35, 84, 89, 11, 52, 34, 79, 65, 2, 88, 49, 29, 31, 94, 1, 74, 97, 51, 99, 37, 10, 47, 57, 81, 73, 76, 63, 58, 0, 38, 39, 27, 33, 8, 20, 21, 46, 66, 92, 36, 6, 30, 53, 17, 48, 64, 55, 28, 85, 50, 54, 12, 80, 41, 77, 69, 93, 9, 91, 13, 42, 75, 68, 86, 19, 3, 16, 78, 87, 45, 43, 56, 59, 70, 40, 24, 83, 98, 62, 5, 96, 4, 67, 60, 26, 23, 72, 95, 44, 82, 90, 25, 7, 18, 15, 22, 71, 61], [78, 53, 89, 93, 7, 84, 81, 95, 64, 50, 58, 35, 59, 63, 20, 76, 80, 8, 23, 28, 79, 52, 55, 48, 66, 17, 60, 65, 25, 29, 30, 9, 73, 39, 69, 3, 98, 22, 15, 87, 4, 37, 43, 5, 11, 83, 91, 40, 51, 33, 12, 92, 6, 67, 41, 94, 45, 88, 56, 36, 0, 68, 19, 54, 70, 26, 72, 77, 32, 34, 97, 71, 99, 75, 61, 31, 86, 82, 46, 2, 44, 96, 49, 74, 10, 62, 24, 16, 1, 38, 27, 14, 18, 85, 13, 57, 90, 21, 42, 47], [26, 30, 60, 78, 75, 48, 73, 52, 51, 57, 63, 90, 27, 36, 83, 81, 41, 44, 82, 37, 10, 64, 91, 4, 59, 95, 21, 24, 77, 56, 43, 38, 62, 55, 92, 0, 94, 20, 86, 66, 35, 80, 53, 25, 17, 18, 49, 76, 23, 89, 13, 15, 68, 8, 22, 46, 1, 42, 3, 34, 98, 88, 69, 31, 50, 65, 84, 32, 47, 61, 9, 19, 99, 85, 11, 79, 70, 2, 74, 14, 87, 7, 72, 5, 12, 58, 67, 39, 16, 71, 54, 6, 45, 93, 96, 28, 97, 29, 33, 40], [77, 66, 20, 30, 42, 23, 0, 49, 7, 64, 54, 27, 96, 97, 39, 84, 2, 51, 71, 17, 4, 92, 94, 95, 67, 69, 73, 75, 86, 37, 74, 50, 11, 79, 29, 15, 56, 43, 22, 83, 81, 61, 14, 3, 36, 44, 58, 10, 62, 19, 72, 80, 65, 24, 18, 5, 40, 90, 33, 9, 47, 76, 8, 59, 35, 91, 99, 13, 70, 88, 55, 16, 31, 28, 85, 45, 60, 25, 87, 82, 93, 12, 34, 68, 63, 26, 46, 48, 21, 52, 1, 78, 98, 38, 6, 32, 89, 53, 41, 57]], [[77, 99, 47, 64, 26, 63, 50, 81, 23, 45, 49, 36, 43, 56, 39, 12, 86, 62, 2, 98, 60, 94, 75, 9, 20, 74, 48, 28, 4, 84, 61, 31, 54, 15, 40, 7, 87, 38, 80, 6, 37, 46, 1, 55, 88, 73, 95, 33, 92, 18, 25, 66, 57, 27, 42, 35, 91, 51, 13, 90, 41, 83, 68, 53, 19, 3, 72, 89, 65, 70, 71, 8, 97, 59, 96, 52, 79, 22, 14, 69, 32, 93, 58, 29, 21, 76, 34, 5, 17, 67, 11, 78, 16, 0, 44, 30, 10, 24, 85, 82], [58, 62, 7, 39, 34, 69, 67, 73, 37, 59, 71, 66, 46, 57, 44, 51, 26, 85, 11, 28, 54, 47, 82, 21, 83, 76, 94, 16, 90, 95, 75, 55, 6, 22, 72, 74, 50, 40, 10, 19, 8, 53, 33, 98, 45, 87, 91, 13, 35, 70, 14, 38, 84, 99, 56, 30, 12, 89, 25, 97, 63, 65, 81, 92, 18, 29, 80, 61, 93, 43, 49, 52, 23, 31, 32, 4, 48, 3, 0, 78, 96, 64, 41, 88, 24, 5, 9, 15, 77, 86, 68, 1, 17, 79, 60, 36, 42, 2, 20, 27], [58, 62, 7, 39, 34, 69, 67, 73, 37, 59, 71, 66, 46, 57, 44, 51, 26, 85, 11, 28, 54, 47, 82, 21, 83, 76, 94, 16, 90, 95, 75, 55, 6, 22, 72, 74, 50, 40, 10, 19, 8, 53, 33, 98, 45, 87, 91, 13, 35, 70, 14, 38, 84, 99, 56, 30, 12, 89, 25, 97, 63, 65, 81, 92, 18, 29, 80, 61, 93, 43, 49, 52, 23, 31, 32, 4, 48, 3, 0, 78, 96, 64, 41, 88, 24, 5, 9, 15, 77, 86, 68, 1, 17, 79, 60, 36, 42, 2, 20, 27], [91, 43, 77, 69, 16, 96, 47, 34, 49, 15, 73, 84, 85, 22, 88, 95, 2, 80, 57, 33, 32, 41, 25, 14, 58, 9, 20, 65, 48, 97, 79, 89, 66, 63, 46, 83, 19, 92, 55, 18, 38, 0, 21, 50, 45, 62, 29, 26, 52, 28, 8, 6, 75, 86, 44, 81, 36, 90, 70, 30, 71, 39, 82, 87, 76, 1, 23, 5, 60, 98, 67, 53, 93, 72, 42, 74, 51, 4, 31, 59, 61, 7, 24, 56, 37, 54, 3, 11, 27, 40, 10, 64, 94, 35, 78, 68, 99, 17, 12, 13], [73, 70, 39, 9, 77, 61, 80, 10, 13, 92, 38, 4, 48, 57, 25, 72, 49, 51, 99, 97, 85, 36, 22, 15, 8, 34, 33, 76, 26, 45, 83, 59, 28, 96, 90, 47, 68, 88, 44, 6, 98, 12, 24, 46, 2, 54, 5, 58, 30, 63, 1, 18, 93, 67, 7, 50, 31, 16, 40, 56, 23, 86, 11, 52, 55, 75, 71, 27, 37, 87, 84, 65, 82, 29, 0, 14, 41, 35, 64, 21, 3, 95, 17, 60, 81, 74, 19, 91, 94, 32, 69, 53, 42, 89, 79, 43, 66, 20, 78, 62], [23, 78, 67, 41, 9, 77, 59, 72, 25, 82, 65, 89, 28, 37, 54, 70, 98, 33, 31, 44, 6, 17, 26, 73, 21, 36, 4, 2, 79, 95, 81, 50, 18, 34, 61, 0, 93, 24, 8, 66, 55, 62, 56, 30, 84, 58, 7, 88, 85, 64, 97, 39, 49, 3, 20, 42, 80, 96, 13, 63, 43, 60, 47, 90, 51, 14, 53, 1, 86, 57, 12, 19, 10, 45, 38, 68, 35, 87, 75, 5, 69, 27, 32, 91, 11, 99, 46, 29, 92, 22, 76, 15, 16, 48, 71, 74, 52, 94, 83, 40], [87, 89, 35, 98, 44, 21, 29, 83, 0, 77, 34, 60, 85, 64, 28, 58, 39, 36, 95, 22, 67, 30, 86, 57, 5, 81, 84, 26, 53, 62, 13, 90, 2, 88, 4, 46, 97, 73, 79, 43, 59, 72, 54, 32, 82, 10, 55, 38, 47, 12, 51, 1, 76, 48, 7, 14, 23, 20, 31, 18, 17, 15, 37, 42, 49, 68, 25, 93, 91, 40, 92, 50, 52, 70, 33, 80, 19, 96, 61, 75, 71, 99, 74, 9, 41, 66, 63, 8, 6, 24, 65, 56, 45, 69, 27, 16, 3, 78, 94, 11], [99, 6, 38, 11, 34, 28, 86, 57, 55, 78, 25, 95, 13, 63, 91, 14, 83, 1, 45, 17, 93, 76, 46, 79, 27, 85, 96, 58, 59, 44, 87, 65, 97, 22, 0, 51, 49, 52, 47, 67, 24, 88, 62, 50, 72, 3, 31, 82, 68, 42, 81, 23, 32, 98, 73, 60, 37, 54, 41, 80, 66, 18, 92, 4, 5, 94, 77, 39, 69, 16, 35, 7, 40, 30, 61, 26, 56, 64, 9, 71, 19, 21, 75, 84, 43, 53, 33, 29, 74, 36, 90, 2, 20, 15, 10, 48, 89, 70, 8, 12], [4, 28, 8, 72, 74, 31, 66, 0, 27, 54, 61, 23, 51, 73, 96, 32, 98, 41, 88, 95, 36, 22, 13, 38, 70, 84, 12, 7, 10, 60, 68, 33, 11, 35, 79, 42, 16, 62, 57, 24, 44, 94, 25, 48, 86, 97, 87, 49, 92, 71, 21, 1, 81, 5, 17, 85, 6, 75, 80, 34, 20, 30, 90, 69, 18, 89, 93, 56, 91, 40, 77, 52, 53, 14, 65, 45, 76, 2, 9, 29, 3, 26, 59, 55, 83, 46, 67, 47, 39, 50, 58, 63, 99, 15, 37, 43, 82, 64, 78, 19], [11, 94, 1, 93, 59, 91, 89, 51, 61, 81, 13, 29, 27, 58, 26, 3, 53, 69, 73, 21, 39, 12, 5, 18, 98, 74, 9, 96, 28, 65, 23, 4, 41, 72, 88, 34, 83, 54, 7, 15, 38, 84, 90, 52, 77, 48, 64, 60, 20, 79, 19, 66, 97, 30, 87, 45, 40, 36, 14, 86, 32, 33, 57, 16, 43, 42, 50, 10, 44, 76, 37, 6, 56, 31, 68, 99, 2, 17, 22, 35, 92, 85, 46, 75, 71, 67, 95, 78, 8, 63, 82, 25, 80, 24, 47, 49, 0, 70, 62, 55]], [[93, 99, 51, 49, 71, 64, 35, 42, 88, 17, 67, 92, 4, 12, 68, 13, 47, 7, 56, 14, 19, 53, 80, 85, 23, 5, 39, 6, 26, 89, 27, 54, 63, 73, 70, 33, 36, 3, 86, 58, 18, 2, 25, 21, 10, 34, 81, 94, 75, 98, 37, 46, 9, 95, 60, 74, 87, 78, 20, 24, 57, 0, 30, 83, 72, 61, 11, 32, 43, 82, 65, 69, 59, 62, 38, 76, 22, 16, 15, 45, 48, 79, 50, 90, 40, 1, 29, 77, 91, 31, 84, 96, 8, 52, 97, 41, 28, 44, 55, 66], [64, 71, 19, 27, 43, 95, 77, 16, 35, 81, 74, 29, 6, 86, 18, 37, 99, 46, 15, 87, 28, 63, 1, 65, 3, 79, 50, 12, 78, 84, 8, 88, 98, 69, 42, 0, 56, 32, 92, 83, 30, 59, 80, 9, 20, 89, 47, 23, 33, 34, 82, 24, 97, 60, 22, 90, 51, 76, 10, 94, 21, 91, 70, 49, 66, 14, 75, 2, 7, 13, 40, 93, 48, 36, 53, 72, 67, 62, 85, 17, 57, 58, 5, 25, 41, 31, 44, 73, 61, 26, 38, 54, 96, 39, 4, 68, 11, 52, 45, 55], [49, 88, 62, 73, 34, 15, 95, 68, 98, 5, 61, 35, 23, 45, 78, 64, 97, 70, 96, 65, 74, 16, 94, 37, 80, 56, 48, 28, 59, 1, 75, 4, 71, 47, 83, 93, 69, 21, 60, 38, 39, 19, 40, 82, 55, 7, 52, 18, 43, 54, 2, 77, 66, 90, 44, 32, 89, 3, 24, 6, 99, 17, 86, 29, 30, 22, 50, 81, 41, 42, 0, 9, 53, 58, 57, 25, 20, 12, 26, 51, 92, 87, 36, 31, 85, 63, 14, 8, 91, 11, 79, 27, 76, 84, 67, 33, 72, 13, 10, 46], [45, 15, 69, 88, 51, 28, 34, 80, 30, 42, 38, 90, 47, 17, 84, 49, 21, 55, 46, 96, 37, 97, 72, 85, 94, 29, 10, 66, 76, 82, 18, 86, 87, 25, 43, 92, 19, 89, 2, 93, 98, 40, 48, 53, 75, 99, 11, 62, 12, 60, 3, 24, 4, 6, 63, 81, 41, 20, 68, 9, 57, 52, 0, 44, 14, 16, 91, 27, 79, 73, 59, 61, 78, 7, 67, 1, 70, 83, 74, 64, 26, 95, 54, 65, 33, 39, 5, 50, 36, 35, 13, 23, 58, 71, 32, 77, 31, 22, 56, 8], [41, 43, 66, 69, 22, 23, 71, 2, 33, 38, 86, 51, 55, 59, 82, 96, 45, 97, 73, 34, 70, 21, 8, 58, 84, 90, 24, 25, 32, 78, 17, 27, 47, 68, 37, 72, 63, 77, 87, 89, 50, 16, 83, 54, 12, 56, 64, 62, 39, 92, 91, 53, 29, 76, 52, 94, 42, 81, 20, 98, 40, 79, 44, 10, 31, 0, 57, 19, 75, 67, 93, 6, 7, 11, 74, 26, 85, 5, 1, 49, 4, 61, 95, 3, 36, 9, 14, 13, 15, 48, 80, 46, 30, 65, 99, 18, 60, 88, 35, 28], [5, 56, 10, 81, 42, 35, 12, 94, 34, 13, 8, 0, 49, 17, 7, 69, 30, 1, 65, 14, 39, 2, 58, 76, 54, 31, 50, 46, 11, 27, 22, 61, 74, 64, 91, 18, 48, 63, 71, 57, 95, 87, 47, 67, 77, 53, 88, 23, 3, 83, 29, 86, 43, 60, 70, 78, 21, 99, 36, 66, 20, 62, 85, 4, 80, 98, 79, 82, 97, 15, 96, 52, 51, 6, 40, 93, 28, 41, 72, 45, 68, 16, 32, 75, 84, 89, 26, 55, 9, 59, 73, 24, 25, 33, 37, 19, 90, 44, 38, 92], [62, 28, 97, 69, 65, 46, 27, 96, 29, 73, 89, 42, 16, 36, 44, 63, 80, 60, 11, 54, 87, 92, 75, 81, 57, 26, 70, 49, 76, 10, 95, 84, 56, 22, 20, 9, 21, 61, 1, 47, 34, 19, 66, 0, 33, 91, 45, 3, 2, 90, 88, 43, 51, 12, 7, 18, 24, 85, 86, 8, 78, 38, 55, 30, 6, 35, 15, 93, 14, 99, 98, 82, 52, 74, 4, 50, 79, 37, 77, 17, 41, 71, 58, 53, 68, 39, 67, 25, 5, 83, 94, 13, 48, 32, 23, 59, 31, 64, 72, 40], [93, 20, 18, 22, 94, 27, 39, 59, 4, 11, 6, 75, 98, 62, 63, 81, 44, 53, 25, 95, 74, 57, 76, 5, 70, 60, 99, 12, 56, 85, 41, 67, 46, 19, 28, 1, 23, 80, 32, 68, 31, 51, 82, 55, 78, 77, 58, 69, 38, 87, 91, 79, 96, 52, 47, 73, 83, 89, 65, 3, 92, 14, 43, 66, 61, 37, 84, 54, 33, 88, 35, 71, 42, 90, 72, 50, 7, 40, 0, 24, 9, 29, 49, 45, 15, 21, 86, 64, 16, 36, 34, 17, 26, 10, 2, 13, 8, 97, 30, 48], [33, 3, 7, 64, 74, 23, 42, 25, 68, 85, 5, 8, 83, 17, 56, 79, 70, 73, 15, 6, 36, 18, 94, 97, 72, 22, 11, 96, 40, 58, 66, 49, 62, 86, 78, 67, 26, 98, 90, 48, 14, 2, 82, 91, 9, 76, 69, 44, 50, 47, 53, 71, 92, 12, 59, 37, 19, 60, 39, 13, 77, 16, 55, 41, 84, 31, 65, 27, 99, 51, 4, 45, 80, 46, 57, 21, 28, 81, 54, 29, 61, 88, 52, 43, 75, 20, 1, 10, 0, 35, 30, 32, 95, 38, 63, 87, 89, 24, 34, 93], [37, 25, 50, 66, 86, 23, 76, 27, 83, 97, 89, 35, 32, 41, 33, 87, 14, 59, 48, 61, 52, 3, 73, 67, 24, 56, 93, 22, 7, 70, 77, 28, 91, 30, 68, 29, 60, 8, 94, 13, 43, 17, 88, 57, 81, 34, 15, 95, 79, 96, 72, 84, 55, 46, 58, 10, 12, 38, 11, 99, 53, 42, 65, 44, 31, 21, 82, 6, 92, 26, 51, 5, 39, 63, 40, 9, 49, 18, 78, 80, 71, 74, 90, 2, 54, 47, 85, 75, 69, 45, 0, 16, 19, 1, 64, 98, 4, 62, 36, 20]]]; +const sbtable2 = [[3, 5, 8, 6, 0, 9, 7, 1, 2, 4], [1, 3, 9, 4, 2, 0, 8, 7, 5, 6], [0, 5, 1, 7, 9, 8, 6, 2, 3, 4], [6, 4, 7, 8, 3, 0, 9, 5, 2, 1], [2, 3, 8, 1, 9, 7, 6, 0, 4, 5], [3, 4, 1, 7, 2, 8, 6, 0, 9, 5], [6, 1, 8, 3, 0, 4, 2, 7, 5, 9], [9, 3, 7, 5, 2, 4, 0, 6, 1, 8], [6, 1, 5, 3, 0, 8, 7, 4, 2, 9], [9, 7, 4, 5, 1, 2, 3, 0, 8, 6]]; + +const ibtable = [[[11, 38, 3, 63, 36, 39, 79, 19, 87, 68, 76, 51, 20, 56, 77, 61, 52, 73, 74, 94, 45, 31, 99, 28, 29, 90, 81, 96, 65, 75, 13, 32, 70, 21, 55, 33, 9, 15, 92, 14, 82, 97, 78, 37, 49, 0, 80, 57, 58, 7, 1, 89, 98, 53, 64, 5, 6, 66, 43, 83, 10, 50, 47, 84, 62, 71, 4, 67, 86, 42, 35, 34, 91, 12, 17, 69, 44, 48, 85, 30, 16, 95, 54, 23, 46, 18, 88, 59, 40, 60, 41, 25, 27, 22, 2, 24, 72, 93, 26, 8], [28, 58, 74, 34, 6, 14, 16, 46, 87, 24, 59, 57, 23, 88, 75, 65, 79, 38, 82, 13, 49, 99, 8, 94, 15, 19, 0, 96, 41, 95, 45, 35, 1, 91, 2, 52, 42, 76, 90, 84, 20, 54, 4, 63, 25, 5, 47, 85, 93, 12, 51, 81, 71, 69, 22, 17, 36, 64, 77, 80, 98, 53, 44, 18, 10, 68, 97, 61, 56, 70, 92, 27, 40, 9, 60, 7, 72, 21, 43, 3, 33, 32, 50, 26, 67, 62, 39, 48, 73, 86, 29, 89, 37, 78, 55, 66, 31, 30, 11, 83], [4, 16, 22, 66, 37, 14, 47, 89, 59, 60, 51, 92, 71, 70, 96, 13, 17, 85, 58, 93, 81, 69, 28, 90, 78, 39, 63, 88, 0, 75, 2, 53, 23, 99, 94, 68, 54, 74, 41, 29, 8, 26, 50, 98, 82, 95, 42, 7, 24, 77, 30, 9, 21, 1, 87, 62, 46, 15, 43, 38, 36, 55, 49, 57, 52, 56, 91, 65, 11, 84, 6, 73, 97, 33, 83, 27, 35, 25, 40, 32, 18, 31, 86, 48, 45, 3, 79, 76, 72, 64, 44, 20, 80, 19, 10, 5, 61, 34, 67, 12], [80, 91, 71, 26, 75, 8, 22, 92, 7, 70, 65, 51, 89, 31, 81, 30, 83, 47, 44, 85, 55, 19, 57, 87, 74, 6, 73, 40, 49, 32, 52, 78, 0, 12, 54, 15, 64, 28, 4, 24, 68, 17, 72, 53, 1, 94, 58, 88, 11, 82, 43, 86, 60, 63, 99, 96, 37, 77, 67, 33, 18, 5, 41, 59, 16, 36, 79, 97, 61, 23, 56, 48, 98, 38, 66, 21, 34, 29, 10, 3, 93, 46, 50, 39, 14, 9, 2, 13, 69, 42, 62, 35, 27, 90, 25, 76, 20, 95, 45, 84], [48, 16, 54, 47, 9, 39, 81, 91, 33, 53, 63, 21, 50, 85, 97, 90, 49, 36, 84, 74, 51, 76, 37, 67, 59, 58, 23, 20, 65, 82, 7, 77, 12, 31, 46, 1, 5, 14, 3, 30, 94, 95, 2, 34, 70, 89, 40, 87, 43, 79, 64, 57, 68, 26, 56, 44, 88, 61, 0, 24, 71, 18, 60, 4, 80, 96, 27, 15, 6, 13, 98, 29, 28, 25, 72, 93, 55, 75, 52, 66, 11, 8, 86, 45, 22, 83, 17, 10, 35, 38, 73, 99, 62, 41, 19, 69, 78, 92, 42, 32], [23, 19, 88, 44, 5, 39, 75, 81, 30, 14, 49, 54, 62, 55, 18, 83, 77, 76, 74, 92, 6, 95, 52, 36, 15, 27, 53, 38, 28, 50, 48, 99, 78, 67, 90, 87, 16, 41, 58, 65, 79, 11, 68, 84, 24, 97, 64, 47, 9, 22, 43, 86, 37, 8, 33, 17, 93, 61, 25, 72, 57, 98, 42, 80, 13, 89, 2, 12, 31, 56, 26, 85, 3, 29, 66, 63, 82, 10, 20, 94, 51, 0, 1, 4, 21, 60, 34, 35, 32, 45, 59, 71, 46, 69, 7, 96, 91, 40, 70, 73], [89, 62, 33, 19, 21, 97, 15, 2, 83, 22, 65, 30, 55, 7, 63, 73, 39, 61, 44, 37, 11, 26, 31, 79, 91, 0, 72, 68, 23, 87, 28, 24, 45, 74, 98, 14, 70, 54, 88, 42, 35, 59, 46, 16, 27, 92, 69, 66, 94, 32, 75, 77, 64, 57, 50, 71, 10, 3, 67, 81, 90, 58, 99, 5, 82, 85, 25, 52, 12, 8, 48, 49, 76, 96, 80, 20, 29, 34, 53, 51, 86, 93, 38, 84, 9, 36, 6, 60, 1, 78, 13, 95, 41, 17, 47, 18, 43, 40, 4, 56], [40, 68, 88, 47, 43, 28, 67, 23, 42, 99, 48, 3, 12, 27, 79, 25, 6, 55, 19, 80, 81, 62, 83, 69, 39, 73, 36, 30, 44, 82, 70, 52, 31, 34, 58, 74, 54, 2, 13, 45, 93, 49, 75, 72, 29, 87, 5, 7, 17, 76, 90, 63, 84, 51, 59, 35, 20, 97, 22, 65, 57, 66, 78, 86, 11, 9, 71, 98, 53, 56, 15, 46, 92, 0, 26, 21, 32, 38, 77, 91, 4, 24, 61, 85, 94, 1, 96, 64, 8, 41, 33, 50, 18, 60, 10, 16, 37, 95, 14, 89], [96, 23, 99, 42, 94, 91, 19, 53, 41, 25, 39, 73, 70, 72, 33, 35, 88, 2, 63, 49, 95, 60, 48, 97, 5, 54, 47, 40, 98, 18, 57, 28, 67, 92, 10, 79, 13, 76, 8, 55, 90, 62, 50, 87, 65, 82, 84, 21, 0, 14, 45, 44, 20, 38, 17, 3, 81, 16, 58, 4, 31, 29, 86, 15, 43, 64, 26, 52, 46, 69, 37, 68, 6, 22, 61, 7, 83, 71, 30, 75, 85, 78, 24, 27, 89, 9, 80, 34, 66, 77, 36, 93, 56, 59, 1, 12, 51, 32, 11, 74], [75, 99, 97, 8, 15, 48, 6, 25, 60, 90, 91, 95, 23, 3, 89, 77, 22, 78, 94, 55, 98, 35, 53, 96, 18, 52, 12, 16, 50, 20, 49, 9, 17, 13, 57, 44, 14, 47, 86, 56, 88, 41, 29, 32, 70, 1, 62, 37, 85, 38, 59, 36, 5, 68, 71, 69, 67, 27, 39, 4, 54, 0, 84, 45, 61, 73, 79, 93, 58, 66, 10, 76, 51, 92, 19, 87, 24, 7, 28, 2, 11, 80, 81, 33, 64, 74, 46, 65, 26, 72, 40, 82, 34, 42, 21, 83, 31, 30, 43, 63]], [[98, 58, 34, 65, 83, 74, 88, 5, 89, 46, 80, 43, 18, 87, 9, 28, 71, 90, 4, 36, 40, 11, 39, 31, 76, 92, 82, 48, 66, 41, 49, 99, 78, 79, 97, 86, 75, 68, 3, 7, 62, 64, 26, 22, 13, 77, 54, 50, 10, 96, 15, 35, 94, 73, 57, 93, 16, 61, 37, 38, 53, 2, 63, 23, 67, 72, 95, 70, 29, 33, 45, 47, 27, 24, 69, 44, 55, 85, 14, 8, 91, 12, 42, 6, 84, 81, 19, 25, 32, 51, 1, 17, 52, 56, 60, 0, 59, 30, 21, 20], [26, 63, 99, 57, 77, 53, 9, 75, 76, 80, 46, 97, 37, 14, 1, 12, 35, 20, 0, 15, 28, 19, 48, 41, 67, 30, 60, 69, 29, 34, 73, 10, 51, 47, 66, 82, 7, 98, 39, 96, 8, 62, 42, 3, 95, 5, 11, 13, 90, 94, 32, 31, 83, 64, 36, 88, 72, 52, 38, 54, 45, 17, 61, 81, 78, 44, 79, 55, 56, 86, 2, 40, 16, 24, 4, 71, 49, 33, 23, 92, 84, 74, 65, 43, 87, 59, 89, 68, 22, 70, 25, 58, 21, 85, 6, 50, 27, 93, 91, 18], [22, 31, 11, 72, 37, 70, 90, 60, 24, 56, 28, 69, 54, 85, 5, 98, 1, 76, 59, 20, 86, 32, 61, 49, 63, 42, 74, 53, 84, 3, 95, 23, 15, 36, 4, 81, 6, 21, 19, 27, 17, 83, 30, 45, 25, 65, 10, 50, 80, 66, 46, 75, 93, 82, 78, 99, 97, 68, 8, 13, 58, 94, 41, 14, 48, 52, 29, 79, 91, 89, 9, 55, 57, 2, 39, 92, 0, 44, 18, 62, 73, 96, 34, 88, 16, 77, 71, 43, 33, 40, 7, 12, 87, 51, 26, 47, 64, 35, 67, 38], [0, 80, 63, 52, 49, 69, 15, 87, 55, 60, 22, 91, 31, 89, 78, 28, 48, 12, 10, 42, 82, 23, 29, 18, 21, 2, 19, 7, 68, 37, 54, 90, 81, 43, 57, 94, 26, 95, 96, 88, 14, 51, 79, 71, 66, 76, 34, 24, 30, 9, 62, 44, 77, 65, 6, 27, 4, 97, 38, 36, 59, 3, 1, 50, 72, 46, 64, 35, 20, 11, 53, 13, 58, 39, 74, 8, 83, 75, 40, 98, 17, 99, 85, 32, 92, 67, 84, 5, 25, 56, 16, 47, 70, 93, 86, 61, 73, 41, 45, 33], [64, 57, 56, 7, 86, 9, 65, 16, 1, 63, 71, 26, 53, 98, 69, 5, 84, 28, 36, 58, 54, 99, 42, 74, 68, 3, 88, 22, 82, 97, 85, 45, 21, 66, 43, 59, 83, 51, 89, 87, 31, 12, 95, 52, 60, 17, 80, 27, 72, 93, 10, 39, 91, 30, 75, 61, 24, 8, 23, 2, 18, 73, 94, 6, 38, 44, 13, 40, 48, 4, 81, 37, 96, 46, 19, 49, 34, 50, 0, 20, 14, 15, 25, 92, 33, 29, 77, 90, 78, 67, 62, 41, 35, 47, 79, 32, 11, 70, 76, 55], [24, 99, 28, 52, 64, 3, 63, 16, 15, 87, 47, 6, 59, 98, 13, 78, 57, 81, 56, 94, 0, 37, 70, 73, 65, 83, 90, 92, 60, 82, 67, 40, 74, 34, 91, 2, 33, 85, 21, 54, 12, 31, 84, 55, 53, 49, 36, 25, 39, 20, 29, 93, 51, 76, 42, 96, 71, 86, 95, 66, 45, 19, 8, 58, 22, 69, 80, 79, 89, 17, 61, 18, 88, 38, 72, 75, 48, 30, 7, 10, 11, 35, 23, 9, 26, 4, 62, 44, 1, 43, 46, 14, 41, 77, 97, 27, 68, 32, 5, 50], [90, 80, 22, 27, 16, 23, 11, 31, 8, 75, 54, 82, 68, 66, 10, 40, 95, 99, 14, 42, 56, 88, 12, 55, 38, 6, 79, 84, 26, 92, 4, 67, 48, 5, 46, 77, 19, 53, 97, 34, 64, 73, 58, 47, 18, 39, 81, 59, 74, 62, 87, 98, 50, 1, 25, 9, 72, 69, 61, 60, 86, 3, 24, 28, 45, 30, 96, 36, 57, 83, 89, 63, 0, 33, 17, 7, 94, 15, 43, 2, 44, 41, 20, 85, 32, 65, 93, 49, 91, 52, 71, 37, 35, 13, 21, 51, 70, 29, 78, 76], [95, 50, 72, 0, 68, 98, 49, 53, 56, 41, 54, 22, 57, 78, 66, 31, 52, 29, 86, 30, 62, 26, 32, 46, 42, 48, 14, 21, 88, 94, 77, 92, 7, 63, 91, 28, 93, 38, 90, 71, 34, 25, 11, 83, 55, 70, 97, 82, 89, 76, 10, 99, 9, 45, 60, 39, 44, 16, 17, 37, 47, 79, 33, 36, 59, 8, 80, 23, 1, 18, 64, 51, 61, 81, 75, 40, 35, 73, 13, 65, 12, 4, 19, 85, 96, 6, 2, 58, 27, 43, 5, 87, 20, 15, 3, 24, 84, 67, 74, 69], [38, 33, 29, 88, 49, 47, 60, 69, 75, 12, 44, 89, 35, 45, 23, 30, 21, 28, 65, 86, 81, 40, 93, 97, 67, 2, 94, 9, 61, 92, 90, 32, 62, 36, 58, 51, 37, 73, 50, 63, 39, 43, 16, 71, 46, 91, 13, 7, 20, 72, 41, 59, 70, 48, 10, 52, 5, 34, 76, 15, 87, 6, 98, 18, 57, 77, 24, 79, 27, 19, 3, 0, 8, 95, 74, 64, 42, 4, 68, 31, 84, 54, 99, 25, 1, 80, 85, 26, 83, 11, 56, 55, 78, 66, 82, 14, 53, 22, 17, 96], [26, 12, 62, 5, 78, 53, 31, 46, 51, 8, 69, 80, 32, 68, 76, 42, 29, 87, 28, 75, 40, 91, 58, 7, 88, 92, 82, 96, 70, 50, 47, 65, 85, 3, 48, 73, 90, 89, 97, 84, 81, 39, 43, 79, 64, 54, 2, 41, 38, 10, 24, 22, 25, 93, 44, 23, 49, 37, 14, 95, 72, 74, 15, 11, 55, 98, 99, 0, 9, 16, 18, 20, 63, 30, 57, 19, 4, 17, 67, 35, 60, 45, 59, 56, 36, 77, 66, 33, 27, 71, 86, 1, 13, 34, 21, 61, 6, 94, 52, 83]], [[10, 87, 64, 11, 25, 97, 93, 18, 99, 38, 17, 72, 50, 23, 90, 57, 98, 12, 29, 46, 19, 77, 42, 15, 73, 52, 53, 89, 35, 20, 9, 41, 79, 13, 95, 48, 85, 54, 61, 94, 0, 74, 62, 40, 78, 68, 24, 28, 86, 21, 59, 14, 82, 84, 92, 58, 34, 31, 6, 16, 75, 81, 43, 47, 7, 3, 2, 37, 67, 8, 66, 22, 30, 32, 71, 44, 70, 1, 36, 26, 33, 63, 80, 83, 91, 76, 56, 39, 69, 55, 96, 60, 27, 49, 65, 88, 5, 4, 51, 45], [73, 87, 48, 43, 71, 40, 88, 23, 60, 35, 30, 5, 75, 25, 59, 95, 58, 79, 4, 89, 96, 17, 38, 6, 39, 9, 68, 81, 3, 90, 93, 99, 16, 42, 21, 45, 74, 84, 77, 65, 63, 98, 11, 51, 0, 33, 91, 22, 69, 34, 31, 20, 46, 2, 76, 54, 15, 62, 13, 70, 92, 55, 82, 47, 78, 7, 24, 27, 86, 1, 56, 61, 12, 44, 85, 57, 49, 19, 18, 67, 66, 52, 72, 53, 83, 41, 64, 50, 26, 94, 32, 80, 28, 10, 37, 14, 8, 97, 29, 36], [60, 50, 53, 78, 63, 90, 11, 33, 21, 24, 20, 55, 8, 25, 6, 58, 3, 98, 44, 82, 96, 14, 1, 59, 92, 75, 51, 36, 30, 64, 72, 40, 16, 94, 2, 74, 93, 85, 12, 10, 43, 32, 42, 39, 79, 97, 17, 38, 89, 29, 68, 52, 49, 0, 34, 19, 70, 84, 54, 9, 23, 71, 65, 28, 83, 56, 67, 57, 13, 18, 77, 5, 4, 88, 41, 22, 46, 76, 48, 61, 81, 45, 86, 35, 47, 87, 91, 99, 73, 66, 27, 37, 31, 15, 7, 80, 62, 95, 69, 26], [49, 73, 63, 66, 38, 35, 32, 96, 87, 26, 36, 92, 58, 6, 17, 47, 29, 84, 11, 18, 67, 45, 78, 4, 52, 81, 59, 30, 91, 54, 56, 89, 48, 46, 20, 79, 1, 62, 9, 53, 10, 95, 88, 34, 40, 80, 41, 64, 83, 55, 43, 7, 24, 61, 77, 5, 14, 93, 16, 21, 85, 39, 76, 50, 57, 65, 37, 60, 28, 19, 2, 97, 42, 33, 13, 68, 90, 25, 69, 99, 98, 74, 3, 8, 12, 15, 82, 71, 31, 23, 75, 27, 51, 94, 86, 0, 44, 22, 72, 70], [30, 32, 52, 21, 15, 79, 53, 40, 56, 44, 55, 6, 63, 39, 61, 4, 93, 43, 23, 99, 38, 66, 88, 18, 1, 86, 33, 9, 82, 76, 70, 51, 48, 69, 85, 11, 5, 91, 59, 77, 49, 75, 22, 87, 65, 41, 26, 50, 47, 98, 57, 10, 58, 62, 46, 28, 20, 71, 78, 95, 0, 72, 80, 73, 92, 36, 96, 37, 68, 2, 35, 83, 90, 25, 13, 24, 34, 42, 45, 74, 67, 16, 84, 97, 19, 64, 27, 14, 31, 12, 54, 60, 3, 8, 17, 89, 81, 94, 7, 29], [1, 18, 25, 13, 57, 53, 92, 95, 94, 88, 10, 82, 34, 83, 7, 28, 55, 11, 5, 58, 8, 9, 74, 99, 52, 32, 62, 45, 65, 50, 41, 56, 96, 44, 38, 47, 3, 39, 81, 19, 2, 22, 49, 12, 40, 67, 89, 76, 64, 70, 61, 21, 31, 54, 51, 17, 46, 30, 24, 60, 66, 26, 77, 63, 37, 35, 23, 6, 4, 87, 79, 97, 20, 48, 36, 85, 73, 71, 27, 43, 0, 15, 69, 78, 59, 86, 75, 33, 42, 84, 91, 93, 68, 80, 16, 98, 90, 72, 14, 29], [30, 16, 10, 67, 83, 81, 42, 94, 35, 59, 22, 5, 53, 61, 1, 96, 68, 45, 95, 66, 36, 37, 97, 87, 77, 93, 86, 33, 49, 13, 43, 14, 0, 34, 7, 2, 41, 21, 31, 32, 76, 55, 62, 72, 90, 71, 38, 23, 46, 12, 51, 19, 6, 44, 52, 48, 73, 24, 29, 74, 85, 99, 80, 28, 47, 9, 39, 84, 64, 57, 75, 98, 88, 26, 17, 63, 27, 56, 69, 8, 54, 25, 91, 78, 3, 50, 65, 70, 11, 4, 92, 60, 40, 58, 15, 89, 82, 18, 79, 20], [60, 88, 79, 35, 40, 43, 52, 4, 17, 31, 84, 44, 50, 94, 91, 38, 87, 25, 92, 62, 14, 97, 37, 18, 86, 28, 65, 90, 19, 29, 30, 75, 68, 49, 69, 11, 59, 41, 89, 33, 47, 54, 98, 42, 80, 56, 78, 99, 23, 82, 9, 48, 21, 1, 63, 22, 58, 95, 10, 12, 26, 74, 85, 13, 8, 27, 24, 53, 61, 34, 64, 71, 66, 32, 83, 73, 15, 67, 0, 20, 16, 6, 77, 45, 5, 93, 76, 39, 57, 2, 96, 46, 51, 3, 55, 7, 81, 70, 36, 72], [35, 56, 77, 58, 23, 83, 91, 81, 53, 70, 20, 74, 84, 50, 79, 51, 88, 44, 45, 71, 37, 26, 54, 48, 27, 43, 0, 12, 95, 97, 1, 63, 67, 98, 59, 40, 13, 19, 31, 87, 99, 16, 57, 30, 17, 92, 55, 68, 5, 46, 64, 8, 7, 42, 90, 33, 29, 9, 85, 24, 2, 69, 32, 10, 21, 65, 39, 86, 52, 62, 76, 89, 82, 6, 78, 4, 47, 28, 3, 75, 41, 15, 18, 14, 66, 73, 38, 80, 61, 49, 11, 22, 34, 93, 36, 25, 94, 96, 60, 72], [6, 90, 16, 43, 20, 55, 94, 8, 62, 59, 47, 32, 81, 67, 42, 35, 71, 19, 54, 49, 2, 88, 38, 5, 53, 77, 85, 11, 73, 34, 3, 72, 95, 58, 82, 64, 44, 29, 93, 14, 56, 98, 4, 37, 45, 75, 86, 60, 87, 7, 31, 17, 89, 97, 10, 70, 36, 99, 46, 63, 76, 41, 48, 84, 9, 52, 1, 24, 83, 25, 68, 18, 50, 26, 30, 27, 61, 0, 91, 33, 51, 40, 79, 39, 15, 74, 28, 78, 69, 96, 57, 65, 21, 80, 22, 23, 12, 13, 92, 66]], [[93, 42, 18, 65, 28, 87, 39, 35, 71, 23, 96, 90, 15, 58, 78, 33, 92, 88, 49, 64, 24, 84, 77, 8, 97, 50, 4, 53, 27, 83, 95, 31, 80, 47, 86, 55, 11, 40, 37, 14, 34, 60, 54, 12, 94, 9, 41, 2, 26, 10, 6, 57, 75, 63, 32, 43, 13, 52, 82, 73, 20, 30, 17, 5, 3, 68, 51, 89, 62, 79, 69, 70, 66, 45, 25, 22, 85, 0, 91, 76, 38, 7, 99, 61, 29, 98, 16, 36, 44, 67, 59, 56, 48, 81, 21, 46, 74, 72, 19, 1], [78, 91, 97, 77, 75, 85, 32, 2, 40, 86, 38, 18, 56, 47, 50, 87, 27, 92, 64, 39, 98, 23, 33, 72, 84, 58, 16, 99, 19, 65, 55, 73, 74, 42, 4, 48, 95, 8, 51, 3, 37, 82, 96, 69, 14, 44, 12, 21, 76, 70, 36, 15, 71, 41, 20, 31, 54, 13, 0, 9, 94, 67, 1, 60, 81, 61, 11, 6, 90, 5, 49, 10, 34, 7, 35, 30, 25, 88, 79, 93, 66, 62, 22, 24, 52, 17, 89, 45, 83, 57, 28, 46, 63, 68, 26, 29, 80, 59, 43, 53], [78, 91, 97, 77, 75, 85, 32, 2, 40, 86, 38, 18, 56, 47, 50, 87, 27, 92, 64, 39, 98, 23, 33, 72, 84, 58, 16, 99, 19, 65, 55, 73, 74, 42, 4, 48, 95, 8, 51, 3, 37, 82, 96, 69, 14, 44, 12, 21, 76, 70, 36, 15, 71, 41, 20, 31, 54, 13, 0, 9, 94, 67, 1, 60, 81, 61, 11, 6, 90, 5, 49, 10, 34, 7, 35, 30, 25, 88, 79, 93, 66, 62, 22, 24, 52, 17, 89, 45, 83, 57, 28, 46, 63, 68, 26, 29, 80, 59, 43, 53], [41, 65, 16, 86, 77, 67, 51, 81, 50, 25, 90, 87, 98, 99, 23, 9, 4, 97, 39, 36, 26, 42, 13, 66, 82, 22, 47, 88, 49, 46, 59, 78, 20, 19, 7, 93, 56, 84, 40, 61, 89, 21, 74, 1, 54, 44, 34, 6, 28, 8, 43, 76, 48, 71, 85, 38, 83, 18, 24, 79, 68, 80, 45, 33, 91, 27, 32, 70, 95, 3, 58, 60, 73, 10, 75, 52, 64, 2, 94, 30, 17, 55, 62, 35, 11, 12, 53, 63, 14, 31, 57, 0, 37, 72, 92, 15, 5, 29, 69, 96], [74, 50, 44, 80, 11, 46, 39, 54, 24, 3, 7, 62, 41, 8, 75, 23, 57, 82, 51, 86, 97, 79, 22, 60, 42, 14, 28, 67, 32, 73, 48, 56, 89, 26, 25, 77, 21, 68, 10, 2, 58, 76, 92, 95, 38, 29, 43, 35, 12, 16, 55, 17, 63, 91, 45, 64, 59, 13, 47, 31, 83, 5, 99, 49, 78, 71, 96, 53, 36, 90, 1, 66, 15, 0, 85, 65, 27, 4, 98, 94, 6, 84, 72, 30, 70, 20, 61, 69, 37, 93, 34, 87, 9, 52, 88, 81, 33, 19, 40, 18], [35, 67, 27, 53, 26, 79, 20, 46, 38, 4, 72, 84, 70, 58, 65, 91, 92, 21, 32, 71, 54, 24, 89, 0, 37, 8, 22, 81, 12, 87, 43, 18, 82, 17, 33, 76, 25, 13, 74, 51, 99, 3, 55, 60, 19, 73, 86, 62, 93, 52, 31, 64, 96, 66, 14, 40, 42, 69, 45, 6, 61, 34, 41, 59, 49, 10, 39, 2, 75, 80, 15, 94, 7, 23, 95, 78, 90, 5, 1, 28, 56, 30, 9, 98, 44, 48, 68, 77, 47, 11, 63, 83, 88, 36, 97, 29, 57, 50, 16, 85], [8, 51, 32, 96, 34, 24, 88, 54, 87, 83, 45, 99, 49, 30, 55, 61, 95, 60, 59, 76, 57, 5, 19, 56, 89, 66, 27, 94, 14, 6, 21, 58, 43, 74, 10, 2, 17, 62, 47, 16, 69, 84, 63, 39, 4, 92, 35, 48, 53, 64, 71, 50, 72, 28, 42, 46, 91, 23, 15, 40, 11, 78, 29, 86, 13, 90, 85, 20, 65, 93, 73, 80, 41, 37, 82, 79, 52, 9, 97, 38, 75, 25, 44, 7, 26, 12, 22, 0, 33, 1, 31, 68, 70, 67, 98, 18, 77, 36, 3, 81], [34, 17, 91, 45, 63, 64, 1, 71, 98, 78, 94, 3, 99, 12, 15, 93, 69, 19, 61, 80, 92, 81, 33, 51, 40, 10, 75, 24, 5, 87, 73, 46, 52, 86, 4, 70, 89, 56, 2, 67, 72, 58, 49, 84, 29, 18, 22, 38, 95, 36, 43, 35, 37, 85, 57, 8, 76, 7, 27, 28, 55, 74, 42, 13, 77, 31, 60, 39, 48, 68, 97, 79, 44, 54, 88, 82, 21, 66, 9, 23, 59, 50, 47, 16, 83, 25, 6, 30, 41, 96, 90, 14, 62, 20, 65, 11, 26, 32, 53, 0], [7, 51, 77, 80, 0, 53, 56, 27, 2, 78, 28, 32, 26, 22, 73, 93, 36, 54, 64, 99, 60, 50, 21, 11, 39, 42, 81, 8, 1, 79, 61, 5, 15, 31, 59, 33, 20, 94, 23, 88, 69, 17, 35, 95, 40, 75, 85, 87, 43, 47, 89, 12, 71, 72, 9, 83, 67, 38, 90, 82, 29, 10, 37, 91, 97, 74, 6, 86, 30, 63, 24, 49, 3, 13, 4, 57, 76, 70, 98, 34, 58, 52, 96, 84, 25, 55, 44, 46, 18, 65, 62, 68, 48, 66, 41, 19, 14, 45, 16, 92], [96, 2, 76, 15, 31, 22, 71, 38, 88, 26, 67, 0, 21, 10, 58, 39, 63, 77, 23, 50, 48, 19, 78, 30, 93, 91, 14, 12, 28, 11, 53, 73, 60, 61, 35, 79, 57, 70, 40, 20, 56, 32, 65, 64, 68, 55, 82, 94, 45, 95, 66, 7, 43, 16, 37, 99, 72, 62, 13, 4, 47, 8, 98, 89, 46, 29, 51, 85, 74, 17, 97, 84, 33, 18, 25, 83, 69, 44, 87, 49, 92, 9, 90, 36, 41, 81, 59, 54, 34, 6, 42, 5, 80, 3, 1, 86, 27, 52, 24, 75]], [[61, 85, 41, 37, 12, 25, 27, 17, 92, 52, 44, 66, 13, 15, 19, 78, 77, 9, 40, 20, 58, 43, 76, 24, 59, 42, 28, 30, 96, 86, 62, 89, 67, 35, 45, 6, 36, 50, 74, 26, 84, 95, 7, 68, 97, 79, 51, 16, 80, 3, 82, 2, 93, 21, 31, 98, 18, 60, 39, 72, 54, 65, 73, 32, 5, 70, 99, 10, 14, 71, 34, 4, 64, 33, 55, 48, 75, 87, 57, 81, 22, 46, 69, 63, 90, 23, 38, 56, 8, 29, 83, 88, 11, 0, 47, 53, 91, 94, 49, 1], [35, 22, 67, 24, 94, 82, 12, 68, 30, 43, 58, 96, 27, 69, 65, 18, 7, 79, 14, 2, 44, 60, 54, 47, 51, 83, 89, 3, 20, 11, 40, 85, 37, 48, 49, 8, 73, 15, 90, 93, 70, 84, 34, 4, 86, 98, 17, 46, 72, 63, 26, 56, 97, 74, 91, 99, 36, 80, 81, 41, 53, 88, 77, 21, 0, 23, 64, 76, 95, 33, 62, 1, 75, 87, 10, 66, 57, 6, 28, 25, 42, 9, 50, 39, 29, 78, 13, 19, 31, 45, 55, 61, 38, 71, 59, 5, 92, 52, 32, 16], [70, 29, 50, 57, 31, 9, 59, 45, 87, 71, 98, 89, 77, 97, 86, 5, 21, 61, 47, 41, 76, 37, 65, 12, 58, 75, 78, 91, 27, 63, 64, 83, 55, 95, 4, 11, 82, 23, 39, 40, 42, 68, 69, 48, 54, 13, 99, 33, 26, 0, 66, 79, 46, 72, 49, 44, 25, 74, 73, 28, 38, 10, 2, 85, 15, 19, 52, 94, 7, 36, 17, 32, 96, 3, 20, 30, 92, 51, 14, 90, 24, 67, 43, 34, 93, 84, 62, 81, 1, 56, 53, 88, 80, 35, 22, 6, 18, 16, 8, 60], [62, 75, 38, 50, 52, 86, 53, 73, 99, 59, 26, 46, 48, 90, 64, 1, 65, 13, 30, 36, 57, 16, 97, 91, 51, 33, 80, 67, 5, 25, 8, 96, 94, 84, 6, 89, 88, 20, 10, 85, 41, 56, 9, 34, 63, 0, 18, 12, 42, 15, 87, 4, 61, 43, 82, 17, 98, 60, 92, 70, 49, 71, 47, 54, 79, 83, 27, 74, 58, 2, 76, 93, 22, 69, 78, 44, 28, 95, 72, 68, 7, 55, 29, 77, 14, 23, 31, 32, 3, 37, 11, 66, 35, 39, 24, 81, 19, 21, 40, 45], [65, 78, 7, 83, 80, 77, 71, 72, 22, 85, 63, 73, 44, 87, 86, 88, 41, 30, 95, 67, 58, 21, 4, 5, 26, 27, 75, 31, 99, 52, 92, 64, 28, 8, 19, 98, 84, 34, 9, 48, 60, 0, 56, 1, 62, 16, 91, 32, 89, 79, 40, 11, 54, 51, 43, 12, 45, 66, 23, 13, 96, 81, 47, 36, 46, 93, 2, 69, 33, 3, 20, 6, 35, 18, 74, 68, 53, 37, 29, 61, 90, 57, 14, 42, 24, 76, 10, 38, 97, 39, 25, 50, 49, 70, 55, 82, 15, 17, 59, 94], [11, 17, 21, 48, 63, 0, 73, 14, 10, 88, 2, 28, 6, 9, 19, 69, 81, 13, 35, 95, 60, 56, 30, 47, 91, 92, 86, 29, 76, 50, 16, 25, 82, 93, 8, 5, 58, 94, 98, 20, 74, 77, 4, 52, 97, 79, 27, 42, 36, 12, 26, 72, 71, 45, 24, 87, 1, 39, 22, 89, 53, 31, 61, 37, 33, 18, 59, 43, 80, 15, 54, 38, 78, 90, 32, 83, 23, 44, 55, 66, 64, 3, 67, 49, 84, 62, 51, 41, 46, 85, 96, 34, 99, 75, 7, 40, 70, 68, 65, 57], [43, 38, 48, 47, 74, 88, 64, 54, 59, 35, 29, 18, 53, 91, 68, 66, 12, 79, 55, 41, 34, 36, 33, 94, 56, 87, 25, 6, 1, 8, 63, 96, 93, 44, 40, 65, 13, 77, 61, 85, 99, 80, 11, 51, 14, 46, 5, 39, 92, 27, 75, 52, 72, 83, 19, 62, 32, 24, 82, 95, 17, 37, 0, 15, 97, 4, 42, 86, 84, 3, 26, 81, 98, 9, 73, 22, 28, 78, 60, 76, 16, 23, 71, 89, 31, 57, 58, 20, 50, 10, 49, 45, 21, 67, 90, 30, 7, 2, 70, 69], [78, 35, 94, 59, 8, 23, 10, 76, 96, 80, 93, 9, 27, 95, 61, 84, 88, 91, 2, 33, 1, 85, 3, 36, 79, 18, 92, 5, 34, 81, 98, 40, 38, 68, 90, 70, 89, 65, 48, 6, 77, 30, 72, 62, 16, 83, 32, 54, 99, 82, 75, 41, 53, 17, 67, 43, 28, 21, 46, 7, 25, 64, 13, 14, 87, 58, 63, 31, 39, 47, 24, 71, 74, 55, 20, 11, 22, 45, 44, 51, 37, 15, 42, 56, 66, 29, 86, 49, 69, 57, 73, 50, 60, 0, 4, 19, 52, 97, 12, 26], [88, 86, 41, 1, 70, 10, 19, 2, 11, 44, 87, 26, 53, 59, 40, 18, 61, 13, 21, 56, 85, 75, 25, 5, 97, 7, 36, 67, 76, 79, 90, 65, 91, 0, 98, 89, 20, 55, 93, 58, 28, 63, 6, 83, 47, 71, 73, 49, 39, 31, 48, 69, 82, 50, 78, 62, 14, 74, 29, 54, 57, 80, 32, 94, 3, 66, 30, 35, 8, 46, 16, 51, 24, 17, 4, 84, 45, 60, 34, 15, 72, 77, 42, 12, 64, 9, 33, 95, 81, 96, 38, 43, 52, 99, 22, 92, 27, 23, 37, 68], [90, 93, 83, 21, 96, 71, 67, 28, 37, 75, 55, 58, 56, 39, 16, 46, 91, 41, 77, 92, 99, 65, 27, 5, 24, 1, 69, 7, 31, 35, 33, 64, 12, 14, 45, 11, 98, 0, 57, 72, 74, 13, 61, 40, 63, 89, 53, 85, 18, 76, 2, 70, 20, 60, 84, 52, 25, 43, 54, 17, 36, 19, 97, 73, 94, 62, 3, 23, 34, 88, 29, 80, 50, 22, 81, 87, 6, 30, 78, 48, 79, 44, 66, 8, 51, 86, 4, 15, 42, 10, 82, 32, 68, 26, 38, 47, 49, 9, 95, 59]]]; +const ibtable2 = [[4, 7, 8, 0, 9, 1, 3, 6, 2, 5], [5, 0, 4, 1, 3, 8, 9, 7, 6, 2], [0, 2, 7, 8, 9, 1, 6, 3, 5, 4], [5, 9, 8, 4, 1, 7, 0, 2, 3, 6], [7, 3, 0, 1, 8, 9, 6, 5, 2, 4], [7, 2, 4, 0, 1, 9, 6, 3, 5, 8], [4, 1, 6, 3, 5, 8, 0, 7, 2, 9], [6, 8, 4, 1, 5, 3, 7, 2, 9, 0], [4, 1, 8, 3, 7, 2, 0, 6, 5, 9], [7, 4, 5, 6, 2, 3, 9, 1, 8, 0]]; + +type DecodedAccessCode = { revision: number; serial: number }; + +function crc16(data: BigInteger, bits: number, initial: number = 0xffff, poly: number = 0x8408): number { + let v = bigInt(initial); + let bigPoly = bigInt(poly); + + for (let i = 0; i < bits; i++) { + v = v.shiftRight(1).xor(bigPoly.and(v.xor(data).and(bigInt.one).equals(bigInt.one) ? bigPoly : bigInt.zero)); + data = data.shiftRight(1); + } + + return v.toJSNumber(); +} + +export function decodeAccessCode(code: string): DecodedAccessCode | null { + code = code.replace(/\D/i, ''); + + if (code.length !== 20) { + return null; + } + + let body = _.range(3, 15, 2).map(i => parseInt(code[i]) * 10 + parseInt(code[i + 1])); + let crc = _.range(15, 20).map(i => parseInt(code[i])); + + let boxes = [(crc[3] + crc[2]) % 10, crc[2], crc[3], crc[4], (crc[4] + crc[0]) % 10, crc[1]]; + + for (const [n, i] of body.entries()) { + body[n] = ibtable[4][boxes[n]][i]; + } + + const rv = body[0] >> 4; + + boxes = [(crc[1] + crc[0]) % 10, crc[1], crc[2], crc[3], crc[4], (crc[4] + crc[1]) % 10] + for (const [n, i] of body.entries()) { + if (n == 0) { + body[n] = (body[n] & 0xf0) | ibtable2[boxes[n]][body[n] & 0x0f]; + } else { + body[n] = ibtable[rv][boxes[n]][i]; + } + } + + const serial = body.map(i => i.toString().padStart(2, '0')).join('') + + if (crc16(bigInt(code.substring(0, 3) + serial, 16), 15 * 4) !== parseInt(code.substring(15, 20))) { + throw new Error(`CRC16 mismatch.`); + } + + return { revision: rv, serial: parseInt(serial) }; +} + +export function encodeAccessCode(company: number, serial: number, rev: number = 0): string { + if (company < 0 || company > 999) { + throw new Error(`Invalid company code`); + } + + if (serial < 0 || serial > 99999999999) { + throw new Error(`Invalid serial number`); + } + + if (rev < 0 || rev > sbtable.length) { + throw new Error(`Invalid revision`); + } + + const bodyStr = `${rev}${serial.toString().padStart(11, '0')}`; + const crc_i = crc16(bigInt(company.toString().padStart(3, '0') + bodyStr, 16), 15 * 4); + + const crc = _.range(5).map(i => Math.floor(crc_i / (10 ** (4 - i))) % 10); + const body = _.range(0, 12, 2).map(i => parseInt(bodyStr[i]) * 10 + parseInt(bodyStr[i + 1])); + + let boxes = [(crc[1] + crc[0]) % 10, crc[1], crc[2], crc[3], crc[4], (crc[4] + crc[1]) % 10]; + for (const [n, i] of body.entries()) { + if (n == 0) { + body[n] = (body[n] & 0xf0) | sbtable2[boxes[n]][body[n] & 0x0f]; + } else { + body[n] = sbtable[rev][boxes[n]][i]; + } + } + + boxes = [(crc[3] + crc[2]) % 10, crc[2], crc[3], crc[4], (crc[4] + crc[0]) % 10, crc[1]] + for (const [n, i] of body.entries()) { + body[n] = sbtable[4][boxes[n]][i]; + } + + return `${company.toString().padStart(3, '0')}${body.map(i => i.toString().padStart(2, '0')).join('')}${crc_i.toString().padStart(5, '0')}`; +} diff --git a/amnet-shared/src/card.ts b/amnet-shared/src/card.ts index 65956fb..8958321 100644 --- a/amnet-shared/src/card.ts +++ b/amnet-shared/src/card.ts @@ -1,23 +1,12 @@ +import {encodeAccessCode} from "./card-encoding"; + export const CARD_ID_REGEX = /^(?:[0-9]{4} ?){5}$/i; +export const AMNET_COMPANY_ID = 597; export function generateCardNumber(): string { - let cardId = ''; - - while (true) { - // don't start with a 3 - const firstDigit = Math.floor(Math.random() * 10); - - if (firstDigit !== 3) { - cardId = firstDigit.toString(); - break; - } - } - - for (let i = 0; i < 19; i++) { - cardId += Math.floor(Math.random() * 10).toString(); - } - - return cardId; + // serial between 5000 and 99999999999 + const serial = Math.floor(Math.random() * 99999994999) + 5000; + return encodeAccessCode(AMNET_COMPANY_ID, serial, 0); } /** diff --git a/amnet-shared/src/index.ts b/amnet-shared/src/index.ts index 66be498..35adf48 100644 --- a/amnet-shared/src/index.ts +++ b/amnet-shared/src/index.ts @@ -1,3 +1,5 @@ export * from './api'; export * from './card'; -export * from './gameIds'; \ No newline at end of file +export * from './gameIds'; + +export {decodeAccessCode as DecodeAMAccessCode, encodeAccessCode as EncodeAMAccessCode} from './card-encoding'; \ No newline at end of file diff --git a/amnet-shared/tsconfig.json b/amnet-shared/tsconfig.json index d543ba3..e29de38 100644 --- a/amnet-shared/tsconfig.json +++ b/amnet-shared/tsconfig.json @@ -1,14 +1,15 @@ { "compilerOptions": { - "target": "ES2016", + "baseUrl": ".", + "target": "ES2017", "module": "CommonJS", "noEmit": true, + "strict": true, + "skipLibCheck": true, "esModuleInterop": true, "forceConsistentCasingInFileNames": true, - "strict": true, - "noUncheckedIndexedAccess": true, - "skipLibCheck": true, - "baseUrl": "." }, - "include": ["src/**/*.ts"] + "include": [ + "src/**/*.ts" + ] } diff --git a/amnet-web/package-lock.json b/amnet-web/package-lock.json index 6eb0eee..e3c5646 100644 --- a/amnet-web/package-lock.json +++ b/amnet-web/package-lock.json @@ -56,7 +56,12 @@ }, "../amnet-shared": { "version": "1.0.0", + "dependencies": { + "big-integer": "^1.6.52", + "lodash": "^4.17.21" + }, "devDependencies": { + "@types/lodash": "^4.17.14", "tsup": "^8.2.4", "typescript": "^5.5.4" } diff --git a/amnet-web/src/components/card-creation-form.tsx b/amnet-web/src/components/card-creation-form.tsx index 1d10b2a..11319d2 100644 --- a/amnet-web/src/components/card-creation-form.tsx +++ b/amnet-web/src/components/card-creation-form.tsx @@ -98,10 +98,9 @@ function AimeCardCreationForm(props: { callback?: () => void }) { - + If you've got a card, enter the matrix code here. If not, you can - form.setValue("id", generateCardNumber())}> + form.setValue("id", generateCardNumber())}> generate a new one. diff --git a/readme.md b/readme.md index 736d994..f68f7cd 100644 --- a/readme.md +++ b/readme.md @@ -9,12 +9,12 @@ An Aime Card Switcher for segatools-based games. ## Overview AMNet is designed to simulate the `DEVICE/aime.txt` file, allowing multiple users to log into a game using their phone. -This was originally intended for use with maimai and Chunithm, but should be compatible with any segatools-based game with Aime support. +This was originally intended for use with maimai and CHUNITHM, but should be compatible with any segatools-based game with Aime support. ## Setup 1. Download the latest `amnet.dll` from the releases page 2. Move `amnet.dll` to the game directory -3. Edit `segatools.ini` to use the new DLL: +3. Edit `segatools.ini`, replacing the existing [aimeio] section with this one (read all the comments and change settings as needed): ```ini [aimeio] ; To use a custom card reader IO DLL enter its path here. @@ -26,13 +26,27 @@ This was originally intended for use with maimai and Chunithm, but should be com ; serverName - the name of the server to show to users (defaults to the computer name if not set) ; serverAddress - the address to listen on, including the protocol (defaults to http://+:6070, where + is a wildcard) ; enableKeyboardMode - whether to enable hold-enter-to-login mode. Reads the file set at aimePath for card number (or DEVICE/aime.txt if not set). + ; useAimeDBForPhysicalCards - Whether physical cards should use AiMeDB to retrieve access codes. If the game is using a hosted network, set this to 1 to load the same account data/profile as you would get on a physical cab. gameId=SDEZ ;serverName=CHUNI-PENGUIN ;serverAddress=http://+:6070 ;enableKeyboardMode=1 + ;useAimeDBForPhysicalCards=1 ``` 4. Launch the game, and check the amdaemon console for server startup messages -5. Access the using one of the interfaces (see below), add a new server `http://:6070`, add a card and start playing! +5. Access the using one of the interfaces (see below), add a new server `http://:6070`, import your existing card (or create a new one) and start playing! + +### Physical Cards +AMNet 1.3 adds support for scanning physical cards on iOS devices. If you own a physical AiMe/Banapass/e-Amusement/Suica card, you can scan it using the app and use it in-game. +By changing the `useAimeDBForPhysicalCards` in segatools.ini, you can choose how the card is read on a per-game basis: + +- `0` will send the 20-digit access code on the back of the card to the game and load the save data directly (default option). +- `1` - Send the card's IDm to the game and use AiMeDB to retrieve the 20-digit code assigned to the card. + +Mode `1` makes the app function in the same way to a real card reader and should be used if you want the same access code to show when scanning the card on a cab. +You should also use this option if you're connecting to a hosted server (AquaNet/rinnet/etc). + +Additionally, if `useAimeDBForPhysicalCards` is set to `1` and the game is failing to read the card, make sure an up-to-date version of segatools is being used. ## Interfaces AMNet can be used on most platforms, see below for options available for each platform: @@ -47,7 +61,7 @@ AMNet can be used on most platforms, see below for options available for each pl iOS TestFlight - + Aime/Banapass/e-Amusement/Suica IC cards supported Android