From 8fa49766807cd7151b7951ce0d0d6c194ef772d4 Mon Sep 17 00:00:00 2001 From: Sergey Akkuratov Date: Sat, 1 Jun 2024 17:49:22 +0300 Subject: [PATCH 1/8] =?UTF-8?q?=D0=9F=D0=BE=D0=B3=D0=BE=D0=B4=D0=B0=20?= =?UTF-8?q?=D1=87=D0=B5=D1=80=D0=B5=D0=B7=20Redux?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/pull_request_check.yml | 7 -- package-lock.json | 53 +++++++++ package.json | 3 + src/WeatherApp.ts | 133 +++++++++++++++++++++++ src/WeatherRedux/Actions.ts | 33 ++++++ src/WeatherRedux/Reducer.ts | 19 ++++ src/WeatherRedux/Selectors.ts | 9 ++ src/WeatherRedux/Store.ts | 25 +++++ src/WeatherRedux/Types.ts | 24 ++++ src/declaration.d.ts | 1 + src/externalRequests.ts | 29 +++++ src/images/oops.png | Bin 0 -> 120308 bytes src/index.html | 2 +- src/index.ts | 5 + src/style.css | 96 ++++++++++++++++ tsconfig.json | 6 +- webpack.config.js | 8 ++ 17 files changed, 442 insertions(+), 11 deletions(-) create mode 100644 src/WeatherApp.ts create mode 100644 src/WeatherRedux/Actions.ts create mode 100644 src/WeatherRedux/Reducer.ts create mode 100644 src/WeatherRedux/Selectors.ts create mode 100644 src/WeatherRedux/Store.ts create mode 100644 src/WeatherRedux/Types.ts create mode 100644 src/declaration.d.ts create mode 100644 src/externalRequests.ts create mode 100644 src/images/oops.png diff --git a/.github/workflows/pull_request_check.yml b/.github/workflows/pull_request_check.yml index 2c8b183..43a6826 100644 --- a/.github/workflows/pull_request_check.yml +++ b/.github/workflows/pull_request_check.yml @@ -37,13 +37,6 @@ jobs: - name: Build run: | npm run build - - name: Pack - run: | - npm run pack - - name: Publish - uses: JS-DevTools/npm-publish@v3 - with: - token: ${{ secrets.NPM_TOKEN }} - name: Setup Pages uses: actions/configure-pages@v4 - name: Upload artifact diff --git a/package-lock.json b/package-lock.json index 6781053..95ba7e7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,6 +8,9 @@ "name": "otus_homework_lesson42", "version": "1.0.0", "license": "ISC", + "dependencies": { + "@reduxjs/toolkit": "^2.2.5" + }, "devDependencies": { "@babel/core": "^7.24.4", "@babel/preset-env": "^7.24.4", @@ -2937,6 +2940,29 @@ "url": "https://opencollective.com/unts" } }, + "node_modules/@reduxjs/toolkit": { + "version": "2.2.5", + "resolved": "https://registry.npmjs.org/@reduxjs/toolkit/-/toolkit-2.2.5.tgz", + "integrity": "sha512-aeFA/s5NCG7NoJe/MhmwREJxRkDs0ZaSqt0MxhWUrwCf1UQXpwR87RROJEql0uAkLI6U7snBOYOcKw83ew3FPg==", + "dependencies": { + "immer": "^10.0.3", + "redux": "^5.0.1", + "redux-thunk": "^3.1.0", + "reselect": "^5.1.0" + }, + "peerDependencies": { + "react": "^16.9.0 || ^17.0.0 || ^18", + "react-redux": "^7.2.1 || ^8.1.3 || ^9.0.0" + }, + "peerDependenciesMeta": { + "react": { + "optional": true + }, + "react-redux": { + "optional": true + } + } + }, "node_modules/@sinclair/typebox": { "version": "0.27.8", "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", @@ -7818,6 +7844,15 @@ "node": ">= 4" } }, + "node_modules/immer": { + "version": "10.1.1", + "resolved": "https://registry.npmjs.org/immer/-/immer-10.1.1.tgz", + "integrity": "sha512-s2MPrmjovJcoMaHtx6K11Ra7oD05NT97w1IC5zpMkT6Atjr7H8LjaDd81iIxUYpMKSRRNMJE703M1Fhr/TctHw==", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/immer" + } + }, "node_modules/import-fresh": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", @@ -11544,6 +11579,19 @@ "node": ">= 10.13.0" } }, + "node_modules/redux": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/redux/-/redux-5.0.1.tgz", + "integrity": "sha512-M9/ELqF6fy8FwmkpnF0S3YKOqMyoWJ4+CS5Efg2ct3oY9daQvd/Pc71FpGZsVsbl3Cpb+IIcjBDUnnyBdQbq4w==" + }, + "node_modules/redux-thunk": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/redux-thunk/-/redux-thunk-3.1.0.tgz", + "integrity": "sha512-NW2r5T6ksUKXCabzhL9z+h206HQw/NJkcLm1GPImRQ8IzfXwRGqjVhKJGauHirT0DAuyy6hjdnMZaRoAcy0Klw==", + "peerDependencies": { + "redux": "^5.0.0" + } + }, "node_modules/regenerate": { "version": "1.4.2", "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz", @@ -11750,6 +11798,11 @@ "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==", "dev": true }, + "node_modules/reselect": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/reselect/-/reselect-5.1.0.tgz", + "integrity": "sha512-aw7jcGLDpSgNDyWBQLv2cedml85qd95/iszJjN988zX1t7AVRJi19d9kto5+W7oCfQ94gyo40dVbT6g2k4/kXg==" + }, "node_modules/resolve": { "version": "1.22.8", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", diff --git a/package.json b/package.json index 921e72c..1275065 100644 --- a/package.json +++ b/package.json @@ -51,5 +51,8 @@ "lint-staged": { "*.{js,ts,html}": "eslint --fix", "*.{js,ts,css,md,yml}": "prettier --write" + }, + "dependencies": { + "@reduxjs/toolkit": "^2.2.5" } } diff --git a/src/WeatherApp.ts b/src/WeatherApp.ts new file mode 100644 index 0000000..1656684 --- /dev/null +++ b/src/WeatherApp.ts @@ -0,0 +1,133 @@ +import oopsImg from "./images/oops.png"; +import { selectCityData, selectLastError } from "./WeatherRedux/Selectors"; +import { getWeather, weatherStore } from "./WeatherRedux/Store"; +import { AppStatus } from "./WeatherRedux/Types"; + +export default class Weather { + private readonly mainTemplate: string = ` +
+
+ +
+
+ Couldn't get image of map +
+
+ Wait for city name +
+
+
+ History: +
+ + `; + + private historyList: string[] = []; + + private readonly maxHistorylines: number = 10; + + rootElement: HTMLElement; + + cityNameField: HTMLInputElement; + + cityNameForm: HTMLFormElement; + + weatherBlock: HTMLDivElement; + + historyBlock: HTMLDivElement; + + cityMap: HTMLImageElement; + + loader: HTMLSpanElement; + + constructor(rootElement: HTMLElement) { + this.rootElement = rootElement; + this.rootElement.innerHTML = this.mainTemplate; + + this.cityNameField = this.rootElement.querySelector(".city-name-input")!; + this.cityNameForm = this.rootElement.querySelector(".city-name-form")!; + this.loader = this.rootElement.querySelector(".loader")!; + this.weatherBlock = this.rootElement.querySelector("#info")!; + this.cityMap = this.rootElement.querySelector("#cityMap")!; + this.historyBlock = rootElement.querySelector("#history")!; + } + + init(): void { + weatherStore.subscribe(this.render.bind(this)); + this.cityNameForm.addEventListener("submit", (event) => { + event.preventDefault(); + weatherStore.dispatch(getWeather(this.cityNameField.value)); + this.cityNameField.value = ""; + }); + + weatherStore.dispatch(getWeather()); + } + + async render(): Promise { + const state = weatherStore.getState(); + switch (state.status) { + case AppStatus.ERROR: { + this.loader.style.display = "none"; + alert(selectLastError(state)); + break; + } + case AppStatus.LOADING: { + this.loader.style.display = "table"; + break; + } + case AppStatus.READY: { + this.loader.style.display = "none"; + const weather = selectCityData(state); + if (weather) { + await this.updateHistoryBlock(weather.name); + this.cityMap.src = weather.mapData ? URL.createObjectURL(weather.mapData) : oopsImg; + this.weatherBlock.innerHTML = ` +

${weather.name}

+

Temperature: ${weather.temp} C

+ Couldn't load icon of weather + `; + } else { + alert("Непрдивиденная ошибка - нет данных о городе!"); + } + break; + } + default: + break; + } + } + + async updateHistoryBlock(cityName: string): Promise { + if (this.historyList.includes(cityName)) { + this.historyList.splice(this.historyList.indexOf(cityName), 1); + } + + this.historyList.unshift(cityName); + const p = this.historyBlock.querySelector(`[id='${cityName}']`); + + if (p) { + this.historyBlock.removeChild(p); + this.historyBlock.querySelector("span")!.insertAdjacentElement("afterend", p); + } else { + const newHistoryLine = document.createElement("p"); + newHistoryLine.id = cityName; + newHistoryLine.innerHTML = cityName; + newHistoryLine.addEventListener("click", () => weatherStore.dispatch(getWeather(cityName))); + this.historyBlock.querySelector("span")!.insertAdjacentElement("afterend", newHistoryLine); + } + + if (this.historyList.length > this.maxHistorylines) { + this.historyList.pop(); + this.historyBlock.removeChild(this.historyBlock.lastElementChild!); + } + this.setHistory(); + } + + private setHistory(): void { + localStorage.setItem("history", this.historyList.join(";")); + } + + private loadHistory(): void { + this.historyList = localStorage.getItem("history")?.split(";") ?? []; + this.historyList.reverse().forEach((cityName) => this.updateHistoryBlock(cityName)); + } +} diff --git a/src/WeatherRedux/Actions.ts b/src/WeatherRedux/Actions.ts new file mode 100644 index 0000000..3a862fd --- /dev/null +++ b/src/WeatherRedux/Actions.ts @@ -0,0 +1,33 @@ +import { Action } from "@reduxjs/toolkit"; +import { IWeatherData } from "./Types"; + +export enum ActionTypes { + LOADING = "LOADING", + ERROR = "ERROR", + GET_WEATHER = "GET_WEATHER", +} + +export interface WeatherAction extends Action { + type: ActionTypes; + payload?: unknown; +} + +export function loadingAction(): WeatherAction { + return { + type: ActionTypes.LOADING, + }; +} + +export function errorAction(error: Error): WeatherAction { + return { + type: ActionTypes.ERROR, + payload: error, + }; +} + +export function getWeatherAction(city: IWeatherData): WeatherAction { + return { + type: ActionTypes.GET_WEATHER, + payload: city, + }; +} diff --git a/src/WeatherRedux/Reducer.ts b/src/WeatherRedux/Reducer.ts new file mode 100644 index 0000000..b6e5efc --- /dev/null +++ b/src/WeatherRedux/Reducer.ts @@ -0,0 +1,19 @@ +import { ActionTypes, WeatherAction } from "./Actions"; +import { AppStatus, IWeatherData, WeatherState, initialState } from "./Types"; + +// eslint-disable-next-line default-param-last +export default function rootReducer(state: WeatherState = initialState, action: WeatherAction): WeatherState { + switch (action.type) { + case ActionTypes.LOADING: + return { ...state, status: AppStatus.LOADING }; + case ActionTypes.ERROR: { + const newErrors = structuredClone(state.errors); + newErrors.push(action.payload as Error); + return { ...state, status: AppStatus.ERROR, errors: newErrors }; + } + case ActionTypes.GET_WEATHER: + return { ...state, status: AppStatus.READY, city: action.payload as IWeatherData }; + default: + return state; + } +} diff --git a/src/WeatherRedux/Selectors.ts b/src/WeatherRedux/Selectors.ts new file mode 100644 index 0000000..bdaf0e3 --- /dev/null +++ b/src/WeatherRedux/Selectors.ts @@ -0,0 +1,9 @@ +import { IWeatherData, WeatherState } from "./Types"; + +export function selectCityData(state: WeatherState): IWeatherData { + return state.city!; +} + +export function selectLastError(state: WeatherState): Error { + return state.errors.at(-1)!; +} diff --git a/src/WeatherRedux/Store.ts b/src/WeatherRedux/Store.ts new file mode 100644 index 0000000..5687d21 --- /dev/null +++ b/src/WeatherRedux/Store.ts @@ -0,0 +1,25 @@ +import { configureStore } from "@reduxjs/toolkit"; +import { initialState } from "./Types"; +import rootReducer from "./Reducer"; +import { errorAction, getWeatherAction, loadingAction } from "./Actions"; +import { getCityName, getWeatherExternal } from "../externalRequests"; + +export const weatherStore = configureStore({ + reducer: rootReducer, + preloadedState: initialState, +}); + +export function getWeather(cityName?: string) { + return async (dispatch: typeof weatherStore.dispatch) => { + dispatch(loadingAction()); + try { + if (cityName) { + dispatch(getWeatherAction(await getWeatherExternal(cityName))); + } else { + dispatch(getWeatherAction(await getWeatherExternal(await getCityName()))); + } + } catch (error) { + dispatch(errorAction(error as Error)); + } + }; +} diff --git a/src/WeatherRedux/Types.ts b/src/WeatherRedux/Types.ts new file mode 100644 index 0000000..673c3b9 --- /dev/null +++ b/src/WeatherRedux/Types.ts @@ -0,0 +1,24 @@ +export enum AppStatus { + READY, + LOADING, + ERROR, +} + +export interface IWeatherData { + mapData?: Blob; + icon: string; + temp: number; + name: string; +} + +export interface WeatherState { + city?: IWeatherData; + status: AppStatus; + errors: Error[]; +} + +export const initialState: WeatherState = { + city: undefined, + status: AppStatus.READY, + errors: [], +}; diff --git a/src/declaration.d.ts b/src/declaration.d.ts new file mode 100644 index 0000000..4997750 --- /dev/null +++ b/src/declaration.d.ts @@ -0,0 +1 @@ +declare module "*.png"; diff --git a/src/externalRequests.ts b/src/externalRequests.ts new file mode 100644 index 0000000..7a2e781 --- /dev/null +++ b/src/externalRequests.ts @@ -0,0 +1,29 @@ +import { IWeatherData } from "./WeatherRedux/Types"; + +export function getMap(lon: number, lat: number): Promise { + return fetch(`https://static-maps.yandex.ru/v1?ll=${lon},${lat}&size=300,300&z=8&apikey=21ae407c-6788-4393-bbfa-d1cf463287b0`).then((response) => + response.blob() + ); +} + +export async function getWeatherExternal(cityName: string): Promise { + return fetch(`https://api.openweathermap.org/data/2.5/weather?units=metric&q=${cityName}&appid=862e72718d993f06e2ca165446011711`) + .then((response) => response.json()) + .then(async (data) => { + if (data.cod === 200) { + return { + mapData: await getMap(data.coord.lon, data.coord.lat), + icon: data.weather[0].icon, + temp: data.main.temp, + name: cityName, + }; + } + throw Error(`Во время получения информации вожникла ошибка:\n${data.message}`); + }); +} + +export function getCityName(): Promise { + return fetch(`https://ipgeolocation.abstractapi.com/v1/?api_key=763242ab3637495ba08023d1154aa96a`) + .then((response) => response.json()) + .then((data) => data.city); +} diff --git a/src/images/oops.png b/src/images/oops.png new file mode 100644 index 0000000000000000000000000000000000000000..35e21523bb025d5855ec74c2163e77c94750da63 GIT binary patch literal 120308 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�= zjVY}xsl!enxLF&M-XXLn^&_V&Tahd!jsMREX%7zq}JC@M4r z$R~j12@8|v94J`b@6FR{3d5CjN!8>V&!QX*C&ok=AXy52V+GbrK`-7o#0>R)n5O|9 zwJtJxBpR~s3aVr^5`R)nX|4J`{fH_@X7QQWnjM+jyt~BqojK_**@H*?rqa*&WJsMH z7x_}XTzi`x`o~i4#OcS${ZDPdpGRDFZ3^XMT>60gpBR%=byCD=v+|#OA!IVHook^n;0?YQBQFBd?kI z(@%}hE!$iOt^&+TlO8!}kRRLd;6OKrR|vZUmlhT%9>s<O z260VX2P8UH1v$2l<;7G5yDKq(LralO`%qgs4`iLe4$X-_u>yUT@S(YOpkCuB)S zbD7rX0T=V)^;i1kbNC?h0KiT0ssvTkryv|YqWKObE&=Vs=__o;O;*)&8ttD>4#lwF z|2aW3JkRE-7))L>Ro@$hqb{1t%!e!K(Z>EWc|KQbDml=06~REF@EUX==l2;y{y5#i z`(`K8{)M^lhuH*LL#u9$yqT9gGdCo4C%V|sqm+RBeFZunCy^3w>nZ;umZjDBC;^ZG zW1Yu6y_gkx;i=e{0}F*wqX=n5r3**5hPEkQXo&O1e2N61S=&tR7+H!5IPb^-R`xM# zg&L@l{~Nwd8D4jJL{f++{uG2Z0T0GN=E1XOL-rqEAKTZf2r5W{tFa-&8L5}pq&(?~ zLw=qxuuGtXP@y87ux?6mGs`I+Q?b;z%3n#TFQ4aJazqzsB+g5O9=-)D4dbJwz-7@r z);OM8uFZ~Qi!Sj$q5P>@%4WOAg+6Xb6*`;oK6$f}10vT0&Aepl_& zS3}JR{vztYN@UofjpdnIQ)e>YO{fh&qey$}%|Kf(bfUvlTUSW;^WdyIvf_q>e^AT73kKGEQy-++z0mp};ya@70?JX%cMIBZ(%FaLuN%Le z4Wu`P0e4e$R*Zcqcby%v^?nA#Vg&ij<|~{7IQcBPDkF=Zh-w`LU<3a$P`x!vg%~|# zmgePyYfU!z%|*b-9OYPclW6$B-{}|2VQQd6B0GC6-mRu0d$f@pwuOE9&abRKiU=bz zS(|sr=??YLDA2XWaExkI&NwAC%V@ z81^>3VjQeH{AtVnFQ@d96SJWcYm~0rQGVz%Sn(xK8YC`<^?AwZdlO0$kc>=xtLMQZ zAD2`d*gVorGq-1;ip}Yz(E;5s{Prg|q`>(Bp|;~a+;>~}?QL7TAVkRXFT8!~i{bH_ zX3NrbB+?p$0b7k}hoWX-BFpU&&lZ)3H5+x+{Bex??`wy&CLakdi-wk6g%yy0UWZ4B zaBJPWo?;ue6|Ux+Urxl2&Q8D8^BVPtQfoBKryUJydGJg?fXe$Mti)JRVQl?e@;;n` zNi7-Uq(H;+--wW3#@r9t3-BLY*pb=8rTH>DfHUU@Z?EQukYBbc+lkiB#g|0LI-LIW zeBc1S_orxTC{ixwMNWFjGoI3@68Ne0?N(D(vbACvb8$tSxFe4)oC6Lbk7x)`M zye1qC4)0(iILp{7A*M}jIIax->TrWVUUh`Ej$CWQ=SM3hMCC_foKkb|D0 zqYHXNyQTjw5it&+5S!LB-^9;N$R9m3xsl)G9-I(okYN2=mU^!E32vc_>28%@ThIjp z`*7c%)zR(j^>BOBpOu6X2isDh*gqf=Bmie>2j*(Sx4t(k*RMN<^sXJI1(>3h;OD_8 z$b)oVbiVNTbI1V-{X-`eH+Fg;H}U3EC)x=kJBeANs2`#|w@3b+7AigAN&&A8D=Wirq1=_02_OLn{_ z#%Vecr48@##OG#C|7LGr+iCfemgpy$Hf?->z|9wmjYqk3iGvK|MQEe|kPQi%!93rU#B$e#s*58u@ zHzdj5j+v)i^!_u;nOU*@0Jo? zbH(zc=*T=E1_;L&O(?;&ubT&yNEy|_y-}zt}?swnE+@2;)$XAx_KE7sl4DtDX{U;*&jSlpWO=0b}CtJZ> zBHRA)*J~ZH2TsY05YMwCV?>j*c4Vvzs13Ykq|;Y2li=g~RrCai56kObZuzsj$~0{+ zjj0_;gO@U~IV=Afn_N=~-^_en`0sCAtCakn%SfzhHV%d$TJ{$WJ#T)A*8uatwI7BFi50zvVk_lo{h4)@Mn&o z3x#H(Lt2!W4d&pJMm|cs*qnsNg!|ze5z{$i#Z1$w2F?+`=>zc^#Zlt7JqyTj9p?$3 zkwOL_zAwFH8B!JHKUMj<38`n7uZHC*EWYko9&4)P6s{rVs|b1EA8-U5GTu@6Bn!DKUh)>c2LO&_O8Ug z@f@yEp!LcxThF9fvgXz`iXq1_sbfVf*1jyl7Gv6HLLX)wnPhlyHl!S23M`4c%$JCW zC46%Q&E()2!vEsq%NX}jjn*zr84Brjw7{wJXn zP9GEFh>oCaXJ(#%z2S8MWr-b`?PYmF2#KBIR@VuM&o^WxlZt$aL8H}wM;p)exGT0j!#W(2dX=tu#8nq7mphbImJyViJ+*;sa$PM z=}q!R`{!pb1?u}&N~5j($EW}>x4NHB8H~%Rg5OARlH-&RvLc46lmG9O1J^x%Y=+cD z+#`4!zIrq!Oe2yjf+35mg3E@%f=bfLull>YhqumK;uDyH3EHJ1o0X2EIFU+mXvK}A zMTMPu+4H?Kpey|Axa(1Z`$;+@rA6YkTvRl0G6Vxmg*BM*1T9au3j$R%YPC6aD-B{N zR3@3A7{g@5zKP?s;4^F4;wylO{$1VwDtn^-Bm3Pt+5+u?Q3nG^YonI7C|+NhBL^m!iIsx zVK8UYtPl<(vg5V>r25N_ub4fJOc=d8os%Hks1jSNpp7TbPn8&;1vbM$o|)mwxF17I z@_FfpuW~s(kdZqe_MMZ#e4BhUkC4)u7n1<#ISz6qzp)4b1WHRPad{d=#`hZ5M8M^2 z^;yvYGD`5Ol*uQ)f<;wfqW!UgJR?vjT+rs9Gsac@p~h457wnaA=~vV#ODCY z(6giqIHDJiZRD)=3={u3?OozAY+Yb|D#lYMd5@edJyaL@;H`i_&mEl8wEXp|t#imA z)2Fo4&t;MArFT1(qOs8rayosY+2{JnYpiZ_Cw}q2OQ_O(p3^mRMSor)wBesnD`j;~ z_rXuq8s$~rRlqUuoN}AVWuVdGZ*wO}xn*QtXM%8ciOx%xKY(Gvm&pZ4*t3b?fv1^` z!1z)Uu$3cW?A+pM7D*5J$|)xd8N z5ftWm-#cSp+${x(Y`gz>5s&JD!=J})whru3=jFtr79w4<&Y5*C;(cJgoHhAP@QHM-NUicgatogtBLY1syrYtPWBw3RfI#W1 zHYpD)&XSJF2ZVBnzn0rv>>bzId$XYiNI8s#@+z-K91}O>0Qc^xOL#$C@hkSVXJa<1 zWA0p9FkVEn=n~h@hioQ-0%?pw1vO*B?#W;r{~<5*Ma)3&TO30|m+l6UU|Af=w|>+G z8}ca}3|-zLqFO!o)%6y=+t;QMoREh^r6D`&d6-p60<@&M86 zSx@PSjLtATaLBX#_yvcBtRoR}FD_lZ@AtEC(aFTsYdm^RE%N2R(7D$NJ6(TYaUcGh z@LlKNVp3J>XcRede#0r(TX2@YgPRxJh;$=QgH5HVBPw-ckuw5#Q z?(Q-$qXSHl{`c~BUel}IPMR z)`9cnv4Loj^9!EMLPPneo{2Ed-+%rqWRAnAR+74 zdPl-7Zt4dk{9BR^@i;gsEAgt6J92F zGU=z3##5>mDyFRc9VDK6%KPrwPBR!mJN$`-h{yP0R9-LAY}+P+^+4+|(2(v22%s2~ z?%k^t&td$sPnm?Oxafq*{~eNv{VZXLu=iHn*H%k%d2|uuw3vAH!E27GBx%m+S$#Ku zurI_`)b{~M5CyG4RDHy5mM21*bmAd!gqP@e``c%;9&yHU)NqI z>+EyuWaeD@`2twMnkL+Nw9|+%D|yTjO7QO2K);Q`*TqI5{vnUmq{CMhd1^z}v(pY| zxlZXOUd4fMk2I82^3WH|ZnK=buMk$f1PqhbJp!~t=Dv_&Z6ejl2eux_pHu&?L!Sa* z#(Z7TbIFZpagy&-_50x#vxF{Vk?8Bq2&#kenyXv`3|ag-1iry@Kiirq1)3FU5Z*q6 z;Sy5l*^ORn_e@`z#@wY-$?#z(qG+bZN%Z}uWBE*E8pKX45Dw_dNZt|&THALnREldk z!pd;d`Dd+JJ5Zgc)5^|owAa|uKwai%EXydZBCjYt8S&R3V`+4d?iMpAE1L>+!UcMB z6+PyPu%orcI-th!NC`1(gL0~{4y?jG4nO&$2AAyNNqVLSmKWqB`L0!;yVINzLycK8 z{X=$0$~w(Wu-l-T#l*Do1nVy1^nF%|8}@L+Q@2)aO>#q;lP`yDUV5P{$)qFn+k9-d zf=W<%MWY*pp9jLtA3g4=KIIVT#*m}`8Ip9m1Cv*MwEk7F7@oNsS}cj&9#cSf7SC85 zw4d__y@EjtBg>&Nk;B3Fo?+~Ds;6wyj+;Y{l4XUB1WHHqhR=GX{(i8*;1+_kJ?r&m z|-UG-j`!oaAU0M_EO}d?-PG0o+P*-xqle;+#TgGx$y<03+O! zU+~s!(B?nPIDS8`9n(`Y0T(MA#;C+(Fsz>M`>l*(T?>NL=GP6zo2bbUMaEyww`SlbZDletgFf(9u zAKaWTw>)nR!AJ%<_9B8?orlB5GprO5wnnDS!{C!53zygdcc9-&FSY#^sMnL5QL$bg z0K&0N_VYFLgK7C9UnA_e@_X_ZFjjrF^3WdrGDTK01`jK) zzoQ}&*K3eTDU@vQnC0l$*AHsGcv_c-Ox{AoR~Uv5l|Y$-8q8gu{}%*mR%#pwkFM6@ zd5gf4S$VJ306rgr6c+mFTl7<^;+mKbKvOC7J%FR(UhIx6;|3ynrGm7RUS(lhYjOU} ze12npR$r|%X>J4=Dj>L~+cTkCgLKRu!;-TLFjCL&L#>;4s$h1ZxO6EUw_Z(hrq7q# zUAt+0UWY=({SU_ov(1TR_LtX-_hvp8eK%Gwvrk9uSDPAt#IFR6=`^k1C)GcxtI&@) z9ST!Q<#tR5Ibhv=cbQAeo!_gXfvrUDy8r81#gDEPGGzZPZhnFTtDrNCy{_VlXGMJ9 zd&MnDWw>c@lRXH^Kt}*hl|m|cEA7qXBmrMGE>$FkJG>9tGo`)h<9Y?EQDPV@$Zmdg zmAjPo z$_h%}S^P49({ho!oh{D+vmk8oeX^0uEZDvn`?yBI5!-a{EnskQfIfRRE9b%g_T`OU z9xF#M>+Ax8y5uQ9Nh|s7=tl1Rragw}v+~ z{dVal|K3cncW#fJvDJ1il>I&}o6|V$**c$MVjjziKDvR?iKn1c-XPS>27D=v8n|B} z0>HJY(bL}46GH~kbb@_%)R_fD2d%pL2 zYA%hhx0T;9jT^7F8a*7WuJq}Uo}|8#dG~z!wh89V1E?g3QIh*%?eH)lL$4dxczUQW z`!_iH&rAlp!Pp?P3jwM<#CKe(?BEgR2>9Q5GvLXNUjMN2e!- z#PlobFXZ3T***;HU5h3x=hGJ zeApv@g|FZFe0Sy8u}$5z`23wydga;Y53|G)1C~(|lAI%n5}GpQ8J;SqL-JQw>O7bw ze^Fr?|DY;GJda6@?Jeb#`VJ83_99%#vSI+5M%dx4p7%(1L6SkTTFVA!6VWC~-k zQK%=AGY$}McN&T5AB9`PwS1kT2Ff7O^7n*j5WeJ5qy>TCO}i)e>FYVes~4>07*#J& zA6xl&pf(kMglIg_18iTNH3)GeZwlRm;73B-z4r!+sR?=MruN;Bwtv@{k`N>+|12`^ zWqy&SCm(G78}`{a@F~6`Dp~OjEi-2ZS)dz+1G#mON;2#q7wzECthv@|w5}p8;IA|> zhh@~vMKXJC7?8#c|MC{2=EUN_cuk0ER38@i@q_j5E5CQ+K?hIB2IoDt9!8zB9eQ2j z{y*$Fl7>$_{?|>=1(FDzR%d;iZjN-Qu=tGky5o(3g5>~m3jC_5x&80bxJ+6>8P8}h zyDR=K?KX+>&^%t{RM-H-9(93cN+1@;Bsy6#@X)8wO%F7BzVwTv-xRArDxZ!r^ zx^(>Ny+6Zu`QCvARF?5s$wn$CZGfN`>GzU`g8CABzGM-9P)9KNAaSP#PYPR z)NaT9wK?6|0yTrtXb{J8`ANPfew)g0BADtV8MaYt57BD4is7V{hKjGETE`LNw@gJ5Qe)Ed{!z~ zkt2EE2xWxQ$6lzLtOnEWPHyW!RAY#hrLwpdR;#TN7q4F%Z>20Hwq8CU@&T#}A;Vo} zhtZvR_bTQ2f+`6}U=u0?J)|KJOOM2<#F) zeWwCM{HXyinuHbC0O)VVXx0p6t>UmWR zQNkyZ^HjH?)W7~Dz*~16dY)Q;=<=)aK5Te8z*%Ux-5*Q*OPWYxGsam9ryRfUgx6eS zT`TKwdaWdLT~>+BU?0fWMK%;jMp^@GZLs0leTCaRPY+ZS?E~*p_mys()!0yIE-JFX zcanfn35%LZOSGEHNhkWlz^w`S(&@dpUbu!IqLV#+2|1`Nn#E}I15yp;G}2<E$AVKcF}>&h_l$4GicGrnJWC8=DletoPbeUwuUUCuMHjd2HwiKcFB89?2@ zsq$4kCm!ZdDz|Ff?qRE$8SsZnvM1C1T_l+x;{Pgbfb*Drfdh2KtN+^PDEXDlC|GU6 zj1whJL34N&1A4Zmpi5Ihevlq33?Zq93>{bmtyjYO)Uh+9y;py%HvGZfl-U3IW`|*( zgJnGOW41GPT6f8~6bP%1l&qqMiM0DGpM9XvklWFqPV+JDk-BR4)x!;1)6QQTOyoK_ zfF-X4)EByCxPqkLathNOKH7FXJA7*NY|6C^I)FW$8xdQ&OXv2UWo#P7rQ)@8Qgv?Q zu!1TcoP=wBlkK&%YkFj3pm5oTB%qq(Q__p&ey}oISa_WGvpESR;MUAplVo_GwhLlzkNE&6>b8cZCy5~Twopde3G`M2}EUib>uZ)H=k$N2!vt>GD8 z>D#cCDVV)-zJy|(?L^Bg25dxY=Q`V(6fke2M1;Z+Dv}g4(aViJYG)PzP*m^xGZx=u z?AsKN$t~FP*jD%V&1Z%$t-`+;-f5gGB}PVwVuNMHRSkBz-eYx^Euh=w7${E(#>tE+ zAlEuj6%dYm_Y9^X!!kx8G-N=;GH$!8Yh&T>ND29U0x>}k8NtZI`#2!5xe4=@kkDas zdfXw}8l-Q1MOnZ$g#Ruc+CEnj(M+0I^7mjwk-_@hH}Gw)4IA}qLB2nvNZpPh@&6^s z+rB_&701SB%`fFI@DKJr8kutJll~F=>lp0P^^ww!+ zOTe)8&u!WK`k4?sZ|*0~Wx+{4-UV#)H?OlXwU6C$|0+&-wElCHQ~?(stT)a3*ll^7 zXYy7c^(#^lGIycrZvg${`$Y!39jkf^->Ehjp3wg8T}bYIT-ItK65Ib0(SwCa?4{D- zN?+I;l{vbMcA#GJs_iejNdK{DDAVl+BnK@fW;N{cX;Dx2Je1>7pY zu_9cxDcZRD^Fosoy|$D#q*{SyiNr=K&_^A;wvgVZzAZEc)dT1kWNoABu+KD^&&J6vVf%)K)*2+fl~s#O)|SdES4VfOS6;0#>9e%q_?XZ zi!qB0I{a{2*7o#OyOt>(kcdT;Njbt!mODHqE?h5(Us5n0YntP!d7*(^Fo07<&_7wI*JcQsnl_dN^eDG?*=hXRYX-i3d!PbFMmBzZIM;a!3=4m&Ey zyqyUfoS)vgP1y5H{@18M0=+t_;%R(OYCGuGkO-l${rqWoAD0YT1q}GMXd(1ol3{YG zptF%HAjGXIcZxsl!nNc?2+0$|$2>w%%HO#CRmb~Pa(HqNGzshGCFm16=g1`RDbo>2 ziGI8ShKOzWxC?m*z=EHB3u=q0de&#nWE|PVhF6W`uzu*MBa_W)j3jYw>Q87y&cOyT zVBa9bjmr|0tdUCQ4`fA%+SPH(v;H6(qwM?4Ffjxu*B);qGK&MduJ)-zKRCERR89;n z`TZdAeB+g4iXag2@t2xcbu&w^+_I7Rf2Mq^8foFr<-D)(=M&P)%eO2Qux4hZqNHC1 zp^_+!Eq;NpGC>-Js1dEyc`qW9q%?_V_RaR=!SwRrxuhlbKJnYv+ zA}0c%Ev{G&gL1U6LS?5N`7v9L!7-6d_bp3&=H~W)RJj86x4!ui@b%#MaBEGz;cP>7c&2Xk?Wkyu22Ys_J5;U!sA=>bZjlzThcQZb+yor-m^%!^DS25y zqDstQ(S%>+RH(37Nw*XXyyDrh<;b9D%c09xwF^@xob7ad=fE2la@U~l4vtkLlpV8= z#%!X{p*MYlw&LA%xZ(xQLc_tRRiP@{>8COM7Q~Q&*w|V7F?Z{j$ED|$*nKeEQq7ml zF;Z1S{b4(tl>9is94S^pZHnO z3@rEDsYTS$h%N2wi0Mw~fn5Aly7uiA{zy0^wZp&kJv^tN#c8XG0JH6<2TaHk#c$U| z0cL*uXXPq}b9RtZ+de&SP-pG(9ODNuDFTnQ5hWKJ6U{nZJvEe_+z-HTr-aH+s5OcvAbk{77CpLS1F8gUf; z68$tIl4_W#pT4NJsjv{NZ3AlV;|op?a9lk1M=svUx7i*j>Y6xLam7uiCD2Ff%uunf z`+Bnm+|RujshJBuf_j#;u|O_>rB39lt25D0)2POPHpnV;bnUum2m}g5O@Sltkxsyy ziU*o2h{JB>0$jACW0)s3OmevvUxm?2(fBv7&}=M({ULcuft-d3BleVZ%wm~iXh5?6 z;OmoU8Tu`;QT$8Jj=)2pM}>>h)ZN_EFQB~?SK-RR0x^VL&@i$sTC|p#7yl$|&DT2B zA$tx(*VD59C>4xv6Q;EoaQ~<#P%PpGt$nQS4`2*o2~$mHUR{aE?ZHfL>$=;+W?f2B z*g$L$0xGxP(OwwR?2IFQPZ=KVVL$3@_F4iJ3>KWQ;jX}{$W!@E$NzmNiXqLsRjVdi z3hBtL{Pp)8NDW_~30Qf_Uj^M3qaID=yVElHhXnViV@$72@NG#!hmYI{rGctp$UrG6 zUd^HYWKh#>6$f=cpZN$%Z%pBirF~L31gbg77rvOa-VIJC;6W5(i7@Mql@5WD)sG=Q zHiJ3yU5mkdD%k(>0GP#_o+oiT4qvNu`T;@SdDCiGkrY6GgGgbL$SPUs<-f#;Y;7|5RJ1l7zi;`6 zDO}Ru{MR&)XEh|FMBHkbXnCZj3c|?6^YYup-fn_f(bPMzkgG`SLj1-2$OqkNO_klb znaV%;^6rz1{JM{q+sQCr^RB*qc;EjR*5ByS{oBvPAmCZshB&-8(WBOo)=U!w>d`q> zBQtJ;F%wucX*KBwYgmX7O#piZ2}!ijI`QP)35zKk6cZ@^YZ=bsw~?0+zjkLth;I#k z#|}z>4PGbSJw|8MUz)VrwBJ9*0m|x|M04ZsJ*%fb86s2!ZFW06Qf#VBh1+Ghi}AQW zRE#rt6{6gP;$FYezq$l%^8H$0P=;(dSERLj3J%6}U}{VaWw&jb5!#}?UOzyt*mu#R z0QrpHQ7QPIvE!~m`jf96AD?B-J=_SG)x+Le?=*QopKCYRZz9a^5q*(H)!5o_{35;rP^X`Fz<^nXBd*b^bk;?2Jdger#U6m}R6+lBdooiV z)bUvmZ|iQB=z%Xi+YQ+Uvwfy#1LkJR49)Zf7%=}t#PWO((v4HARo#O=oNvj-y7IuG zs1jYJyAu2T_mOc#4?cgb^22499?Ap!v+w3|3~fw>sgXbo|LBEw_=Xuz-=$aY<5(+~ z0;7!oRZ!uO7@w|LbEF(B)a-V56+31?%5Pgj47OyA-ml-- zmmi%z^3YcRJ1m;8KHu)U&lV|w*)px~x7n%F}YUl6&9=^SN|4w{i4rF2AbfAD}Nyl}>&KV3M*c+(2nWp-R6#%W8 z@?Bn}**FQs)iWSIxG~LlqpH=9Y_(OLM!!$NF5FY^d@_g&p5O5 z9?`y3+-In-s;624es_C=e1GX(7RJM6VyiT9c6B72^mrm@NafNwhtJ^mj{*Wgg+AMQ`Ky=Nsf>LiN-Utl948V13vf%~|}K3{#p z!N%uX741Zhf-8*Ck4dS7ysrN=BsT!193^1>7b3hF>_?8sk(-0|atY5l&MVM35Kq^3 zknQKJQW_MWoiI1}D$pxG-Ep#dx&@{4jzxS>Za}6RB7FG@m-%$VsSjxh?cWNs*+Xz< z2Ym_Ii(yjsq8t0S0Z#Ib_!=|;8G@y8kj%fv;EZBn>HZX8iZ=R_!Ughh?WX|ju&2>7 zs!ew)LD$Bnbj9v*@8%$rChuSga9+vE(J86#A`-rM(4vj2a`%WVT~uzo1O-E6$AxK~ z_qXC#(mbAoq!xb9yjy+3q(@+VwaTx(z^JGg?L94ppZGxM&}-*49-WukR4BGG)B*}a z5F+wME%0@SSA6W3N-DBha&9d6z^Cffb^lSJQ9IJorwapy!~i3_7Dp2f1VRVt!*T7b z*5Yr0WBX44OOtxPJmHI6;hizv7kqcGH{S$@H&r&_Fd0Dq9o^Y=nWsqF0T*9e!B(mj zk%6%0-eK5+j59B%Q9Ow+fXNjafRtwg!L<@vG;AQz53qM!g3l->Aohd)7on6k&N~tz zse<6Ye}a9WiW1jk^C)otLC?sfJ$9Hyhf^u(Kfr{sdhmR}r2mj>#~Bm);kq!o_zT8~ zOb@ik!bJEgYZoZQ59isZe^Ia71C%{DtwAtUa=(WlQ4-Jv__GzSzdzE??RM1`&d*bd zEcDXZQEOd+W|q_%+bVfW7%NFVW5HoRyb$co3J(twz3K{O3;M?JGHYFZow-MCi^K>( zk}8owfU6>aQf9^YryRo#9dZ!>hkj$PgrDmWzs$y{sfUr9G}>hzGv!+GdZaskdHPLA zLkDYoi@_J;^16jE?{PBnB7Sl9k1$_4!WD{i$+-#hLO*}11sTT#fd2gSdgXDZsNhaSgw5)B_Hx`B<$j|_qHcq%Lu)@1n z>#ht*|6jMXHuhj=?{5o7}U-RRX*0o`WY&wUspW_mu_}4(U3+8c-%$Oytn2s#Bm94PG)be+sNP z#%cnO5psI<*i#2X>H`Etg73rGH3P@OyU4;!8Xort4bwPbCKFxM2w9{+bW>J7-+mKJ zDx@Dc$Hrq@X+sdv-V#UVp$w!Z(l?bFF`Q_HB1k_Pt7$(rPl zqel*;X|3s~jp&bceQ*OyrtOMSbYe$cAUkQZ**t4#aEWfids)t&Z@yyvygf_!EuYEw{c}AQ`9~kB3Cz>xeJbB!puy!Q z;-Qp@>iRMM6ju*}?VfvoP)Z`D|F*8WMjE+I7SuSj&B$Li? zzA`y(0K*TKGsD+hN~UP(cpg56<4pm z)!Wp1I!yi^asF%6j-M1}S}-9nqJSFV*9swGaIq~`6^tprg%c6*I=aT0j7=za`yos( zuYid3miYHK!bHN)*FECWf!TC(loeU`XqWzfS?b2ly( z)f7ue-4Bzr6%glb*2!OR6w<1K=%}UI(r;7khxdFO>M7oqN=bi;d-yOPM_+RwYR@-< zxPBgZWn1?8*eq};-8&M&8pY$X?MsJ+G*ApqkEVz8{&xia2v-$OMhVZEp*NE)?~{U zCbBK$ev>ZNIkNG}K`?I-`bO=$5c3Q|!agFs*3g0dqzKeW7LjslWxTE=aFS^=lYZ8I zK;aK_MSVucPNbyziD~Mv(bK;D1xa}{x~gCV!wm1@3-QNxKLLhSiDi%39V z%6uv-5I1$+ah((Brb@fo3ts63ZPZ(L*QJ9kGYagu#-`Q%0G&FHB}78Ee}*EwDsW05m=@WfD(CT8SmC-!$~xV7d{|IK&rdE5QTE*cP3|!LdVGCK7Cxp_uuBO(q7<56eu0VG`|-5rjl8_{R~zx15ak&fN}_M|HEeZ&NOE5C{R z4lkQr_9->(x4?(j)rAmQRkc;_)c}?ejnniocZRd!$G5d!Ju{?f&Kkm<9f3?;Nras> z<>ASp<-A(b>BV1PJjTjse#K~D<{OiOHuh>aM#YJ&FM0-M=Q`K=GDI+|QZWBs$>3U! zYDIF>lfrFdL2yNF%o_(y%{M43WC#pYCz}(&W7vk&k>};5b}MR$cOts4yo*xEW$S=M zzI%9QA)xDD9kX-Cz)AQl?S@oW{>o*(bO$yS+AM;TKK(%&e2ao>k!g-J)~R?+Pc%D2 z|;reU9?mb%UfB@#QQ1OytS5{tA$TMWU5IyRqUGXlXc z1SUdCIK?ZPDuNO=<{zx>sUusbQg^Ys2D*%O39L)ti=>(CDHM&Ed_5Ur$0E8tY+i0a zqs9eOnV%~a+G##5@I~n0OJ`|?r3heUkfPKB$yU|przBwBZ{lc0<2-M|z7;v*!vIvP zN*c1*3TMXoC03mc1D0wg;p`-4eJ&r52_8cF1;^TB3;~2ZLk4cdHh1JoYtL|-LcPxvlPZp4@f|2vszF02_v4}$8Hcj>_=7Uh*bUS~DuqV* zcv13)eQd-Hr;WL!W!w6|XRU!7s0_y?V-+8#Ro*BEhKBAiWndJ5KUZ*@{ z!n*bY3G9IwT>cb`sObBJ3b4iTH_ZZWF-d7?$i|VOqORIQ6ox)oE^<8`2sngr3*_mp z(0NJ3$0rd{uhNk|RSXgY!EPYJFEK^>P<^FX8b$QhKmKYcQTYiEW10BG zd_K`Peo-ZS^fo`}iKsHHb_S79R{G(GN{HVt!=dG_Z(C5B>DG&F-L_Ht&NeUL#0yIm z{%qMi9DOlbhU!{beRl@O|IXp8E)!?f%7Wp;J3trgCd&s$6iI{kR6ME29sBn?FbH>ObZ9Oytp6E2j zm%A8q>Z=85peJ3&iA~R5I>01w$?HJxC1-xiggm0jLN*HoQ6hln@5;~z=7ssd6Rktk z?E?Q6+E8tVJ)dxG-PJS(;}|dil@2g_9iMc=FJj&x-JKIy$K#`?Ao44vizh0R1`}CS zU1vslbvdoVfw1L#Z&4@NHMaj4f^YvrDqCNNuO5qy^kM9%Z4rLK165Mde0yvye10>Hc!@MQ>5)?CjA6eF{<3rR{E4&J!7B`Xcvyb~qeL<9Z+m_Cd>KbZQ;;4km)vP8W5; zUD)3JXjXMfaQ=)S3F==5U#mcrlFHqyBlu1Rv#1mWZ?jdcDn1n%d|#Os>>?7qt%toS zw4#r7>@;dk4?BJdkTpn38x3-?Q(GpCTHysCx7j-D#i4n`cA)joBluRfA-!cETP+8E zb_=L(UV{9vu$(l+CFE`3656sLK#xJE_Uf$$-U@Q^-#1*N7Uvt`Oha-jtnsloF^}&FKbB(q3 za~l~J%Y`}Na!#rZYyc5FI>W4msDx%5eVIt*+9L!6zhu`k+*O~lJpmue z(=B6}{BCB=0~Y6NP5uv)E^)y5f4PJ=nmx<^_5c!2#E_59QiatM+*wTw8A0%;HLBqS zbr-!QMmqO-WV)cYae{J;jsFP75^!+f^UM3Mdf`0`5Q=pM6p7(ml{GqCXK*SjwGYXp z2=8P9{~h~qMajWR5y#|6e6^d6OAt2rSl;T)x72eejfwOwptSf!Tx%|a*crX5Jns9%C^ zs(H0vCzE*m)S#ON{MsdC@>sWm|yfD!OjB`<-f#gQmT;W{IML2&42 zDd#CFyfbabzpBI1Fy}j>rvo0B3H}e382Q8m(OTfs&9I{a`<`DLPUiZ8#N_&%#N;bM z+VEY%bQ7MoQ`aNH>gy8!rOU5KZWY*1c=H2_)(<$CkT)}gTyfH_Vf8EHf&)qZJZR^( zd=ve2EMRz$yfh%-6PXv(QY^(-57^0*Dn1)yp7(nEktP)0yZzNS*aTx^+#`cl1P=Mf z2sC#{r=g}=ub;Ju&PayV98Viz#R6#-W%*GT`!dNR%WYu(^t}6$6c@B<^m? z(hJU8+kynw3Sh^uaE7}=|AokB@mS5B=-wG31TSCndduNiR7B*2WW#`B7B928o81s$ z3?#z9cZnR@X&p7Fk^xTm1W!@bK2i&=4xHgcH0Cha{^a^W%&19?T6@EB_$uN!_Y(~L zF*?U%;G8bumAm-@Tzi_C87crt5N{{|C1d!jG60*&!J`2D5K^El?SQ;xpGN{5Hb5rf zZAGIHz_s(hIG~Kp9yfRrvnRY%LT?wy&mY$md4hr~ZGU8T$OFY3k$DLxr_^F+ozRAP{Rd+lBipVvio5gM6HEnCns|F z@sct95gJ4x0|KAskBBL4T@**Gt*V!JIQN3kX|!Rg6r|H!l@?`oSO=Y3>o8+X@L@K@ z-Ds@Si)~rx5F(Ycsd|}+BalqU z{u#|4MxB2%$Nlvl4Y$abf>U|cCCYtGr4uVrd+eyNR?9_sqN1$YPtWdF0qw~YtF#3a zO~#+KSAjxvi6^{mT!GM>c4$cH;2Wf z=SUZU{nN0PcDJ=Bh>p<*D>Gi04R$>HS8=TX?mJ*d&{*%vD0Od$jQ)JtvDIN<^3#q zDC#!n9na#jMxv=vGRggx0w`J9yiyCLMT5C}z%<6q+X-jjJ_yLb%4WyDGugTc)>542 zDL5?0bu%A+9Z~`H^)=^2ST;@MtKnG$v`Sx*zke{RNa_yBB6R>#l(C1qLB#UovzbT< zUHA4*sCGdnvrDH`o+($vipxgbaB(^}yI#Y00feF9f~QvP#CDXR zA(CYWVt!k6gnyPxwfpR+9Ax2*BmnIqGKE|J(r`qQ{x3o0j#_M+-NZL~?+V($JP27F zXJ)-Gkp4l8BA<}M#QsHy^nBx0KVo!D4izLdP{)(@HK^Wcdm4eaz&c3z%$9WR{5;*Y z&juFA$-bddE;(?C29u3QTEbgAx9*5!MqncN|C0>pm!IS*HhGnu;B_oJf!gIRW$@+^ zw}4K;tU4V1_@ zb+`8jAmI{OB_(cZ?1+18>s0r=_Jq%d1>H4)CyrXy%$;&I}6d-5Ki3eN> z!;q*_lK8&0GZR|`Q^Mnu^OHVHI;Mw(0!NM@&QTZeTDxX*_!o#Nig+u0K+ko$k7ptu zkRfiaVVXbh7R-5$(EyA(bkG2I+~--J{-x{$iBPBCc@|cDlemIidCcZ^MGGI&*_55x zeVX``krIJ}>@T81e0!!1KdA!T3d>WlLs(Aof3HM92HLy#3CaJupy6zSwXg#6?~ib* zR(V zpS-L9usQ->>Y_bZ-)u+V#JRJYP2Z6FnBV#2Jr=sxgzFy{p$^;#I+3-PD6fe=U}h!h zsAU&T+Us4G#1%0rH;?RSjpBRbI~oqh1IQyLzohcDmTCMfn86Tfrl2!MSF$JBgS`i< zKu*vz<^xc-5}7oQXzf3b!I?N<>jLL5Dn}z6PSg2Y9mYrhG}7`<7Wx#d{mSZ6_7849 zZO!u{20N$rmE%TDE>@XmfxpYgB8fL{E?k%|-#53Q1RM+a^nVXqfR~fS=13_U>$C}j zYzOD@q3&=bg0Gm!;cO`}=THWpEi;AEip{T|m_P~;|IF#PVKOTNa-;Y<`1=e17AScJ$sLWhthBIQm@Tr9}-O^1|qg6;aH1#^*>Zv7iS zK|Q9wh#-#ja3tNw_{+v&aZ?us{B}Ss%^w$gD5pD!A5 z9;=TH+h~V13L3{4r&#Wbw9Vh=A4iNha>^?wwqf?)Q01u3maB$6>%d@)xhBN$eat_C z#<#zV%q(CxFf%HQeZEcej*pz~Ihl7lR1g`>jzmkSjfz^Y5v9~-)Mrk+knyEm84`(g zM7icjIx{v78MOtMzbwn_W%>v#``vRfX*5tT^SaUSbcFysPPI(y?Ukc4#UM$8-&uO1 z{j|&|)g0U#c(pROuYiL$;wJqD+2stYR-7*E(vq@d=zQoj67rv5WYHM0TwVfrEJp6+ zylb@(aMH|b`~;Ga=3M}qM`SzuwfXp`>Yff`+fnH&mMXNMA>t;xpSXU+d=yO=;u|iu z!lcy)`O^=~PkLv6q6WhQQ7cba7H~CO;FN}mn^fEa%T0z3ES*^bV-6P3B(S@mLg$or zN*JnLI>iHXwoALS&RW`wQp){);<_Gi?|3Es(~#~2(UrY~-(Rq6Q#zOdO#sbOs%(RI zA7D-N|r*KX7*}YszNPSr~0oT&-pmOBz ze|_ZQzkDlfdy0~{Q}$`bL&%Up|B> zh%=Mz1v9#Ejmm~_L`N+~-%H+soSQ!fzs-NLWrNzLN3^Nub1VMCcE-q^xl;h}l=xD% zz=2M&iQIuQk6oh%ah6WYe@IhX*Nh!t5LY5Y;d6QtI7Pk&5K+aa99h0xRS9Y!L_}b$ z$D5*7#}t~CUpwJUlFJ>>W}U6MoGy5XhOEpT*6tX@sZRp%XKlurgVl*w)bGyuK0s*P zrT2RB)+|b|H2UUTAr#wk!W>Cw&}I6fJ{4)<#7_{7;O|`#p2hc8*q9JFJ-!`$a@Dik zWgA4_csA$A4!ARAYbZe$Um70H7sFZbV{_;ua{hn<2;D>5o`AAI`Pt2pj2ZL6qxcV2 zB&~pAuE=CmFg=z9u36=K4Mypzi?~T><{-&1OMs}Oh{QXwp0>I#Q=0*m zQY5+UouRA)kcX!GnyOQk)mnQ$&j`l2Cm#$_ZyY~WZ>VvO9;<-L`ci`e2V4uE@A%D0 z9d9#j?JFW{2cioVX6uZ$DL-1|G&XO8`XGnV4q$`Mq*1rJxqNmIw#r&+>dGip)`_f6 zTvc6BQ&fMn+>tJt7AT3>Wf-}(m&iw);1e@t);A+};$)X(qB;VSb->k)BF7GW^xl7!8JgHhq(?s6r-4F zj{X{@GS5?dw!VmM8S~R-t4RT)(d46>$J8Z-M0akZ*0iWSvK9ClirsaBTa~N?bmaG8 zs1&0ZCd5siAKF7+_CM_WIwmr0Z!=iZY75`><05KT+>@SO{MN4)M~n`dMvFD?3=gNA zY>O?5Zl?;7MAPi68HBEEE93lwP>X$RsfA$p8ipT)?UfK2>vI&lS+YogyE!7SjLgT_wONppl9V~)mS?>URnvA zaM*P6wR|@9O@77Izngt<2FA^Ei)~+c&yqZh{zZJV=GF^gNdcJd4za%a!FXV-X{=;C z+w?Da_A1Jl7Z0KSwCp27KA~nJFb*2=YgmirgY~8!ThPGL_Zc=GC`%ao(DOg^< zi4MJAjzfcO>=@oZm5x3;;@f&XypcEFLUTo(W-QCT|Ff~}M+OsOMNvPVDF%kTRt$+5 zGGr91PP@K{3Uh#P2mdI>*9O5|hFvi7PP~q!$&v1s10|2?sqK%*itfl9$>gSFGoEs7Cs5M`?Qoe!y;)mw zTCsd(t5_Ay5Ggp2V;9XE?NAT&gqH+q-~}{)@l%qW`UiJKV;BSk*Bx+>{>HJw+qOC= z7Q}Y|i$o|Ey~_BM)Y-7Dywnou-kq&1HU}w;iEC+V_Bhi(u&pe~R$_NA_5bAMs1u3* z3Yv<(nhpisXI0Z!x9^FF^xt1~)=Y{#&GIZ&6PW{#O$u)InKW+cnu+LvzU30Br-Hux zXssUa$knSc*XyeWlNBB;VL&(Q+ikv5VO-wR;f%*mmgwXz1u}UK5O=bF^+g)>{FFSVFvZhSk!rq&=r3A9 zy8TwKCo0eIvG?0;Td{5ByEpgFv8&sc?Iha?@(w<@b|o4Bg6)cML51wH{w_ra3F5dV z9Q5?giPoow5P_}A{30d`1Kj_`w0s)j_nJL+tqUoNT+je4-p1jz=BU+KL=W5u2s$z2 zPxrpD!gD^lnB=EDr-ETES_POrjZ$`?uCpkX3CxIWC;pBzdxnpaS>zU!iQoxbVEjse zAnOy1Ef`rT>(81&BmjvCs^6L@&1@&^6Q?>wJy-5zXd~gvt@xqb;Zh;;TrBuB>u_8? z$02z@5z01>X<=M$qtc;gb$8GE0QNDgA;DwkO+Byb1nPmd49E@8 zvjLJDm(O+l>ZlSam=bONp?IHQ-MII0f@Yd(11bEA7k|46>X)8D70}N`%Q2Wwzmm`3 z=sGkg!&a*o>l&&o?KT_EGEllRvf3N*@CEI zFZv+w;v97aC#1Ip6_T2$R9)yj-9}}Kpn|Q~Vk6q-^qm}Sz|F{9H_H;67g*VDe^T9$8d@`%jQv&m^BN(_9kKYrdnx^w-3kQRxkj7DvGQwM|WyxgQPmL?- zu6Yn>IEqBb?zKyg?$fH^1S~!KkepqRjT~*8wF4hv?#n-%IN^>xA_K$noFug^ru#}4 zGX_Uwrkmn*7;%vdq#q1$-oP*W-MWP4t>7is%@g1VMy*zQ86xGk92gsw2EVjA!oyca z*3eAg;O9cZYCjoa6v7YiOx>@?_w?Pj(Na*!J||EQ77MRYC(I z$1Y0dd#YcP6T+Cer;ef|utvlkZw-Nz(-OA=onbw1%q1e=^$6mV582%|%lmF848FF- z?w%7@34yfpZI;+#Qw^0K`|(NP#I27~39DY!?%VR{H(jZKi0<7X-Rd%9B38^E=;C(w zM3nEm{PM% zl;>yyC;s2}E2ynI~$PqHAyuC;#?WmXp>TIM!+SiZ~*v z^+b;sZ~YZSucPf1(0?iwff-}5%Rn~qXLn?guzALPGoFS_Lf#g+G&ECJzN5>c!Z zm~K`_!TCb{5-Obb9D^rbcfUwn zyR@JE{8I_~)Ss4KimIq;r@Aw2+er{{snmYmaFoRk z=O-ndViMb{XFl`Df6cFmTs{Ux7kgYxp7Y5zy3=Sbl}Wv$`vKVj&)Za=<~vUd->*Ds z=1q8hB8c>vqCQ61B66Dllt-=h811mW5n8He5{{Dc7X@y_uQDW;#oUflcdv^bZun-_>aZ1z5Zl~Kr|@D@HQL;V+BJD z$}%mdeO9sjE9Xnv6w~?fZtNO`5WQW>4A=)=2IO(P>E;?Vcq^-m3S7HBoP^c70=b9& z(hCZK&Yh%;74Ai-?W09Vx;7Kux4LdHM+E*j$UqeFYpRP6my}kK%4P@&7(i6x=NaRC zqz-%S%EN1n4$rVZ1*wTQpJIL1EQ7Frz4AQ_3lJ@E(J+53@}=J@VVZQ_o6-4A zD@md50`fR91qRGpfchrE2Npg%yr}ejEU_4ydl> z&n7Z<0PeiTTVEXO9;H7PQ(bo;ZC5a@WY$ zP+{UAgpQvRFosNtKWV2JkgHjx*`Qdk6Y!axfKeF(805Fs8!1ZNC~gqi0%L;Q-yE`6 za-U|wlOHcDBd6y+^GnUm9pzus1ccEHjs+X1fF+=}7{7_quTkxb`}Cyiyt ze;E>r!ilQK0$^5tbQb?OK|q7*G!16Gxc>)IN#4Rly|?P(>6OG@Lf^+Gr&Wg$gCE7} zbB;sNE()yg;`2r{Xv3HM`qe0aQ!|o!C)N3nb>3KVPp3|2^SR&Kw$3B}>~m$WhHQ5C zGI+#v3!cSYBEwm-Cz-SbKWI7jLqc(0ASu)I=UIcXgkg1C8LkPnpUHou!mU+W7S zm+pxp`FV~jPK`h*^HLNL!d?vSr1Jn`Rv2L8+tP;K-dEUqOue-7YwI=5M{U4wQAzOw z(7pzxBf%a;t%0_>N(gPH1EnR(jI7r zrR*HE$^2d^P3z|*Fwt4nq;F|-mh%ikj$Y(fby6jE{^`wyX+lHx0WGWdX-*8 zXTs_F68CG|tpR!Cn2$8oS7|05Kh}ltt(j?V{n(zbwYKlEn0SY{qa_@hTzzFH-|NQ3 z)cW;1{?h$-K(OBMYVdANBG@Oqq%>zCm)Ye;!Cp8(1K|QO14c-1qS)6w0GfIgKxECK){Q8u_vk6QvpITT z2{&Em8dj`TmrGCm?*pE-^OqtaX_xEoum3+@Af`44JJ-{3o{Qki@KWpn@XJmo2hzxO zYr-)>+ZpQhxdyy%31ZS)>xa3P5sfI_$%^UXvvpK?9ZK<4@ZmKhb7jBwwc5d5*$8bq zqp+shr*;Z+&_#2qPuk+^Sq| zt1e{PlHa3S6|PFBy&R^WEJku&i^fO($J)~$&h7>T^w05~6D-hy@c0JY$%BB?e;Yr} z!r(jux4$pka<&_3KSgeQh$I29KQrPMY>4EMPd7%1R6 zMA+8tv^wZ?nI$dx{{6!g9r&`dzve0v@U4H!h&ybSgba8b;lEQs80$Y+V#7+V**cNF z7FUl{jeJ^o`x#zdu@?4-*a1{SfP~Xw1mOuyXbOjhZU1DS`V>K_cI_lbslV&uRc#<8 zqmce1hq4E%Hy9{*9NiEoIBM-jG=R|u2`M&&YfeL5^xu_=800{ju4Ct+9)9^3yC?bc z;n4rX>hb&otI{OQka7Ho8F6jejEJ;zD5(1Hk{ia2fij67y1SP&%{e}9a z1?jQUc%Pl+4y`kW0J-+n*X@yOi|^nLe$8@vx}mH8Z`tvFv_ocf(Yv=tK69_%y{T7u z)$LNo>7*+yQkx`-7SajX)q`e8QN+=$lGS#VF2{ZU(%%{y=L+tayXFhHQ||hAOOZEh z0lK`;`R_!JncVOGNS$D{O4K@R+d+0x!kn#Rog49u8?Vx_?PHkJQ7KOb4cq;|y znS0FDC$~C&yqnD2E3}yyJ&g_@=DDppUQxd!FJ@n#;ftVrcK>?$$CKq@{lfL~M4i`$ zjGG*haEj8dU{hsv66IVTtQ$m86cm8CpGfA`P7)72ibO=Ndo^PE#UAJ>rFh-5+QaI4 zaF_m|1Je>ZV?78M z$ABovJL<5y+YyxRc~5eWpJTo`ogRm;JHNet8t2HgU>yUS5#(;i;zXZuYaD&*WFF~t ztsy<2U1q!NVZKtFP_fU*@I^RA3rL5rKK{n%*|2*WR5RArEl3By{BLa02q=fj@z7a2 zMJEsen~>&+JxW2Og2MmyvS5S6qI>>$p`z9#j33)7Xp<*$-|x%cR!P^GJXAr~JJz*2 z3!JK{#b0TW!kV}rc-hz_)od~vCKo9rk1vB#1)tuQyxy3~Dvl?vM3=)Eo zL21CFCdhjzG<;Oof{+I!85Kx|*3E{pyep;^oh_CuWt5m)eOdDQK^OcTa(ML zj97EK7?bLfe-hi~<(lNbo=koNc3N5K36K4Pac+o$q6X zASTYTabr?Tb1M6kGrp};7u?KaMJN}VDSwA>)V)g3tyC+l>7SnEX_O1wBGmfqV&4E_ zkJ($Q9Vvb*f-EDo?)59B51C(th$Y^^o@!lH%3AuHjAi>Ydu*rsd_=2VwCQ1II~-t| zajr)>KftTL)w12xG{dtJO2sp(eLn5>WDHl=l-k(5l*)HYL^;r0gvYgut1{rY!XQ#Tvy#MiA z0k^+P$5(|ShOvoOdrba~tkXcr<9VyFy7S`S-c0*z6?$!!hDDAcHv*>(OGC@N^RIBg zkZSQow%vhJhhR}+RT+x9!L^iHvZ9sD3okMBW4b2Q;|BXKaIX`!%87f!lhW0=Yiz!% zKOR%ZN$#zvdCp^bv|yg1kfu!DZ=N?7iLX+n$(^ayfsg4aPS&)IB%A0v%dp)f)+<#} zdHL{e<-;M%)O%Kwd^d4OgR^l+ySgir$%6W-ITz^b+XrGIY2Nl&w!Qh&g;vKM4rzvI z?EY9#1H0Gj(aE%C%4RZGG}NH2(T<1H)UlB_ON4=(&|W@;R;nqh(NRqbdhoy8K4?!;vOqbf!9PC>WGl2OaPR5Xi(JXkaLnmo4fO zR>!jv=@i)z$K63!TzUAtbjr;(N)_n*|9J7uF~+UFl#9u1DkPS$db}U@Yw4XM#~n=1 zP@%>e(yzuzZ4e7}W1)}UX4q^Q5&LxXd4$JF;oVuXT0dQO*POWty!k^V8xNe?NsqmA zzB=sN3;v<#bN2Y2{?jiT%DBw3il!OSyP-rYkHH$Vr_$b6_BFy(+Z5uJVtNP4LziK^ zhC!!|*l{=HTHl%2e!F>=_d%Je%WYQW3F4X0FW+^HPR)VA>u4oaL&uChiS4XD%fy-Q z&A2^aDd(06D|+7T+~k~E>Iwj(Xcgf?{l0=WG2qYVd`NNjKs&{IY)_8Hp2lgv!Nh&I zYaog`-$x_lO4(tfpU46Jk5QKBQfa%L6;A7THcLFF6&wxXTTr!NzA#I7T@giT@5?&U zHKGW0gXPAVraHrSD`qL%*Gd~>TP%O%x#-heH8SD?-}GcRG2~+?yP@4=s4nN*`=R5P z$0_;TU3GDdCtZoHV;_N0oax_|$X+u$iTQu<&pg)jJgG8ON|fbw%0L||D(dRm2VCKM zpiwttEGi1yqVJA7!o1oG*aME)JugDc@V4iiQT-&HY>nrLQ|BSNL1-ivSXi7Xzi!%C zN;Ti9h)8m#)N$}Tiof7mMd}5?zdoTK+W%=Cw_p2h4b;T%x3EMPi(*(A(Ra|hS%pZI zSbbgCV1W%o-}Q#4vG2+qOr(xnu$EV;mDi1+rs6@vlZFxdO>K5nY7E|+shxag=TTyHBw(c z+Vk1ijg!~|?a7c6bf%VU^N*Pi4l|ZJI1v^u`o>t1b;GN^WNm zT&I=UI9P9%@a|oczOFq(cLyWDIV^komy#1pqID@t&e{@b02`2ek-2jg~)mN?9f1OGa@UT3CYjxy>=-j7zoQ;-uM2Hi{#(pR!gzY zvlgJ)QzJ2`@^LV%&ZYRzO1p z(geIPF}=w!qey1+jRl$Ky7AUm0+&Q^nJT~@!)s56tvz?MG_#S^ZBo;R(s?(Ios-^8 zdsth&@<|fGkZ-mFCX_l@Myk?3QZ701e*qVo*E_M0bkX0?2;chcR-~q2;xeFO_@g|c zRD^QNepwN}X5%o**m#J|NY>0x=)s+>j=a(DS^Mg_^TBP0HfK0r$XeLEL~Y(|`mgs5 z!r1cr=1;Hi>e^+g%v+O3%9GzH#2cTmZ3EowW%+e~obiqmZ;cTqW42lSDM6@QQhHlU z6db)|r=p6T8+I~-E;k3LP{%i9h_+{m^;kcQgnjl=W~E1KKe_F2O+66HKV7^V7_}NK zYjwiLu~ArgM%Y{W%Q#Nj{)C+)O+q)~yT9p}*10USn$ZXib~2|;!!q;UowKG8-!=)2 zVf-al%#6I=XjTo=16|<-veefG7Zo29uN&C?WWR8Paq7;;(g@EH}>4$|9pKzG5VujVw2syYl@Ot*c|qv7(Jj3w_W#NxZlixrK~? z%2RGQV>xuw!w)J;%yN+O9Fl7L4C<*7A{jvneCnA%n#Z_kD2MV}^$=&n{SLqE4U5Hm)7Jp(%*7LDK;(pA|(&rixrv_AyzcUzrqDOmEoPXs)a!3m^ zyrV3hg%!>q&H;Zh9R}~c_QzV-NWbV8en~Oz97Ff^(NQgJ_gN}0#gInN~_#ecPqj~#CKhOe}LYQEdqB0gfi=vw%H__%XL31B zvK-^}xnoxJX(RC>=0GE_lTEn%`izvz_72!V+xwHI16GJ3>{Qe#ISs6Y_osFl97wF( zY$!y*N{Sqs;vL(y&XGuw_jUedP1rpY7!v6HEMtV}6}OZ@)DxFrtnEkLi{0N=_or|b z)|DcPyuH%sfuAFfTTE$<%3~w@hr;Uwe!LzSW~s7zPFdgyFb7MDH0HJ2MnwcM7)WlT zdG7}}rg=%Y>inQh8J21?5gDTO+#hWnPibEn3!g3FOjVhl09K;j3;(jiNC zNOvhI-CatvOQ&>qcXy|x@6G>tzrcNV=ggV7=9-zlE8|z@3~o)9ugtv@8Pt6yjuE?! zjFM)Bfm!@zXi*itz>R%Q`(x$W)An!LWzd`d)GPin@&=S&WjweK8&CyrF@2)5si-)| zmj>hlw>)s5uC_-)!Gq4dN5u&|L;d1?^yzYEk|PBO+@$%rQz*Tt7A02Tz!pvKr%>ps ze-hVQlA)#fq_k~?#1@V|eQ?p7XvcMpcMxBU!N1l4YPvUW;{!0fzhaM8mBY-;BtZ~; z3yI`}X=rK}M9%c?Y@kGM)Od4d!CkA^pI$gfJX>MVBesg`08WX}4I#f$uV>9ckbNzb z#C?S9KCl+Q-Bvq+5@UiQU*VC@!R3rYq>yy1sE^1yyvQ zTqJAE-4gza(06SX`X&fMWkH<6-a*#Knucnm;YU)1=HS|=t<#f>lOJp8JQYe|Z1a;A zUq1iXWt*Q|5fBEuvbkUAYaLHAu;_>Ta7ydD2^*rzDH5?ncZNdZcGFZzaVw&~=1g+@4Dds!nJZKz^XU-?joCO@kG}ro2!e=R zBUC`z_9c>C;!vF&5<8a5{tj5q!scDAY*51a$0W(sYOGgCti$a~DY;#g7yd}v;JhCx zO!#0~{cE0;1L$#9`7kfV%g-=?)j@ZanQ?I1yCPr_5*zIK_w0GWY{>Zd;xH+N;R{E( zdygx9RztTI$x~1s|DXkSJ(I~0V%eZ`&2A^d>YR0AL~zT|MF{6%kthJpD&bKN+#kCB zXuG8!v8|rDF;qpfewaT(8>Pp-e399jmu1koX+OAwwzxklE4V zAfo8-`wq&#>;%1!s;ItN@e+#9z`I`f1=(Wb772H(svrrib$e|_(%5>14w})~oaxej zZBbHqqLlU!>C3)h-So>d6YB7OhjJzR-JM%{Ae+Jh$*iz>-YfH(Fqr?Kq|vLM&so1Q z>giWLKic8+5!9hG9f=1vz&I)}%B7XOltc`yjE_v6+~90QU{_Uk+s*7fZprNF_ha`X z;U>>acpN_wOfi!H-`(bdSOH0K{bQB*Ekp70mZi0M0lUq+eLWle@~}`rDyy&Cd>gbj z_xl7BV?$2{2N))*@y#X!Zj+BXpa#a@_$E;)d54>%NCrgsRxL8U&-&$Maq~LO->+0F z5;|IKl*rQl7Z)?yV7)Zyn8A*$-Rka8i(q=?i!XQAv1phOj|0@^oPT_NNkb32tJwI; z+lDCxeWtdLz+cPQC_wF7i))X@Y~SHmGrr2i(azuvYwfu}#wPM%Zt719hU(`|0&|xI zi_AN}IIJVS!Z`(;9V?~M{Q5pt&dkX!0a+T$TRq%6hgWzecqI70AHf$Mb*~n37&y>j zUK0VcrL3NG=cx>$%@@G?q0~X+2Wi=UyZm0WIE+nq%nIEe&wgNwN36rQGE3R=a~#JbAk5 z+c@)(F~@O6)#N+xuTJ=A?jT1+iJ8othsr&<$Sp|fV^K8YC{_PtlJMIkFK?v_N{)n2 z`6lcctSyisOul4dU}b6lWGDP*F=bl)oYU$IjsrS8Ra#Xkjc7?RJko;IG@fzH()Tzy zPK&5X?%mj8uhj6nFpfjt@?g$z5qyBk65_+(xfnf9j zz3iOfMkyYOB48=v83Sz^SsbZt(hcL$x1%=Tx4qGZUGjp?e~6!KkWV3Z7VDK692~>? zO_0H80V4B#DXs_$beO}@m&&AG>Qn*Ik@Fc~mkWqcsIZX0>OE$=6@knGgc2*pOWpDD zqgd}5>U+W!!-zoI&C?7X7HSQCTbNEt*CmFFsG`HU-WXQq z#Lct2>8Y5J(T-gV#~liTa=<4aVx1m(x7e_ZW|S7RP5w1ibh5js|KQecH&>Ia`i`$BB`Va)D= z6aS`DggF@h`MwwA7#m?l08el*KsqU$)oAp3Oy5&5k_1gN-jC<)@EEkc$pfX~TVGZF zOq>s;89N{}r=5Vp2#m|p-SyOTf~f-+2ErTOtYh=WztV?E9J=fsKb5nQVMA~L(WiO| z+Z>Fz{>L>6%BH;8uqIf?p;kt9OL2f)gbk07J&z;6YzOlM@uakgeceU}=GFjo4cAf| zZy(>{?v^F2#ymRLI?7@QlCv-M@*u<3*_hcLIHO%k1y-yNwCYeZ2tZ_+u*fr1Psc}$ z?yQVnI4kd+2LC+#vWCPN6Hd;Ds11HgZ1dL9Bx;s&Q@AwL+LNN5L!MB$%-=A)am36w z;?AV}Tb8S0N9oR+z4Z?i%^84ocC;BbY){?mfg<_|GFX`oIscjyv@HDgEvqjx-&!wX z@IS8WWM=F7-5sG}7@p{_(onSL2fE31HDdPd_4tq((YHBo9PEHqEDAMgo-66r;*hyF z`KrV{VEJcS7EPmCAb6|iC)y}|@Hp4a#H(mtIEI_rR8k@6-FGj`g1opCe&i?x@o6QX zChllwzGzyU(ph%51XE*VY7o-*87cH#IQ^S7?>Q=`dIY7+;+ghAaIMF8ZvbXUXzI$olEB>dBLCwG}P6>R4_t^W@2+fL9=$c#i00+__d59x2 zFa{n8hP<#8=j4a$7%7%EF>KSJ$}lFWyWJw-e_LAWOmDqFJ9bbhqOg)~{H2#Jb1nkU zY|+@NWbQcT(InwoT`cuB<@Jq3>Mp(8aIG#iUXni!YH4IC`7jxhIC2<)SsJ>XIG5!^ zN>Y(EDJGmx)HzMS>6uj)16d!mAwqdi`fUP5I}A>;7~n3LrJ_BB^mjTmlExPuW;+qc z$pC(zuLo@V5WPji~*a>Z}*0ADh@V z-Aq3c;b+fMV@+aP4K2^d5jGXOKgPj|YuZeE)#fjB5PzTVS&Cibgd)hhWj-CsK zfW#vK|1b<>3cAp$clNJf9wSk?e14?K4Ab^jHg+Qz+vmU$-Sxt}`|&u)+I~2dnTp=s+IL(;^X@O4FN+)IS*pQWS^t3(-=FYcf4sCtRW!5g==80+Xw_ z%;f;Asd(KHAJO&zWd+uFUpF;42DB66TbR{iISIrpDH~Jl;zPIdLmP-Z9Z;f}I_=)r z&#RgII>C>PQq&*;v$KO%Von4WNlVilKO<`FnC5)Cdr_ z166SIY@TbF%{K zVsA{`*2|yJK}GOJHYJ{>)@pNGl>DE)v#DvXIECrLlX9%-p({JkQ;AW51 z8^ZzS$pyu%fcInVy`4?^RDgNt4FY6dZ+D0ab6KtB$5Ua#TOg-!6reDkbt$3^v9i{O zS8ZUNQ zpqtQ`wsZ#P3f{_SkAM)49VqQwm49ah<%?|I%2s^`Rb}@()uw2bIZMnLMkT+?8PIqU zQAS0JO1PAQgF~+1*BoJUt9aG&$XFC@oJ`%;%UE+|{U+L(Ts_@6>dn7hX_(xz#$721 zZOWbGt_a8H(Ek>AeDE@1G~`eV78T~Nwxj3o=*MmVvA81+bgN}k0p=V+61+~b!9S3{ zEam@@!`MUm4Ij^W$RIZOvlY!;?uZVH+z|N1PNC|o9|!aNT=AJMoh^NKgGrnHpHMgz zEE*c)%;g<^{ad|HfH$Ee9gv3-ctrL?PgT6bOR@`OmVy9F z9xwRJJMF(!$6}9=JRZ)X<9W3~s+XD&zs&#*vlQU!p{KOeb8 ziRmOL5^5lrzNLU*!v7cAfXfpdR7so7R14+#yjBK*%C>DA_IeHK&l$TEnuQ*S81bgk zvha@&y0+}!%9Fp!F=sN!~Cp4nOM>1-> zHt!W!n5}1G{ml=b3oBlt{LZhkHZ7ic1CiOBVFp~>(FD8k0vUDue{u~*Y1DR*k5+Y& zrAvu-x_&L93bIjDT<-v%l+sNTXbkM;G<*%UU{9|}WXx*TFH{DE|HH3ZBQCnyhB>7pbt^GlJ^h|301>?kwQB+F_OW!SfccUa>Xn zBiFhBRy%!sX{5;)9p(gc`)^x+30?~iD*EW9{<2n>?5~Y1iHv?4L>ulIEjQD0SDaXb zDu1+~aw?&S+IE6`CfQF!p4$`DJH87V`45&MPD1R8I{cqhsqTrfp|#!Z+G|et>t#uD z!q;a%MwizdceMJpxGOiwT0iNx9&61>C=UH7E;S|J5@;3Ub4PVrVkEVV)**@cm`$~A zxk(^4r-tR!&W_6_Z2NVp3c!7X_{KbAu*aio+(UzzbW~l9BN6tjjCw12?l?7#h#$=6 zx?7^O;k{L}NAl)IU=)48qDt^?SaXwQa9v|{Tm*rDe&9BB=3xT0)@neJasTc4HSF*u zUE(;k8<`jq734IOvEIKeai$#$8DxoPqW}0eNCnII^gr5N45d4HoizLrnketcL>Ok^ zJ(+0ps_BIWW0}Fo-xdkh8yc|jMY@e!vg`IE4`whYlT5Y}_5BA+p)VA@K#@|@TGs~b z+on8=iqJP7)V=l{0I7JrH zukC8n&piXR9wn@Yew4M(Xp`?*IXy!{^D*e&n=stXbiMMw&K z&p*_~Ynxy5eMZ5aW@4v~%$P0tm#=({-lgat=6(i1rU49Ut_8sTeb|M&h^Qi_t~ z_$eo#So>2vkPHt?kL0_+mQ=4Tm*pd-gijh0rbk?NGUgSO|9ke|nj3XSLy-E4H%aw{ z;v7}{#7pe3CG%~DT}$Q8%YSNqd^3|-mst0PW~irXRWd^B7EHA9;Xx{?pwzMWK<$_M z$lqyNYfSNop&vDCGYhtH|E~Xi=m56YB$Rtm?pnTml5_*|vYnF(-=C|dMiYEy+M5FF z)2t$BA<1~@w8$uV{1s!@2LnD~HTS#bI5w1VOu!iBnM|%3k+dBV*o2RN3@Qm%7!G3C zPY4%@sP~iDDT?+4vbG0<;V&aERnn@{$Rw+z;A0U^{K{%hTIm-5X^-~rT+gNXyi!*d z!^Ws}kKycSUD_fx#lH-CDoMsJ3Ij{Par8rUBc(^q_0y_AL|q|-V^Jy6!k><`9kEK$ zRfy2l$Eq%26FbH}7FD>t)H(lIJ6`ni;dbyQ7jUbk!(_J8+b)I?ACzoDeX|1m;ve-A z&;rWR!4q1wS{JkQL!adNWQ{Z*D5L6D3QbQDo@jB@1bIF zb0}qt#0l$#+{qY8t8i%BhPMV&8G}8zTB1<>iRt{N8l+({7=MUePD>)HA`Fy(=Pr{D z*?;gY%b6*ij6pTg4SET!63$D)_^@(;wXKDw{`i`nkU57odNa4p4+-J0 z>Cfo!b98)no3KAR7y)IA_Ynnn-L)YW1ImL1iR3ns63N|-JZ$tsg4h-+rs`9G_q@*g z;-}@$zo^A`PzAA==ws0q)n`s%?ig6GOU2q<%LpMk26Fx0CVwfnz?C9IAc$6G)DpRv|x>g4)T zmTscPCy`I(Xj|`li32^1e8>2TNr-CA2MIc?&n@1j`yV+c&pYod!*+g5^VJ{Rc}~QH zQ1XV}Y;C%QR7AZ4k9Hbk8v_zc8iBd^yVwx;HY#PKv32K^!awg3j zr0hv$@F1Jk0&G0~1V|dEYrcPHAPji{W4qv^lXO7KOA)={JZG^(mz2?)C+E)ad*oOC z2b!^g($KLDgd}0uT;N@EvY_)hh{{_io{ju6h*QUFLDMZO+}qdSs|QM9)ui5>D44{* z;Oq4om2?prS70UTq{io8QyE^u%UxMF4A%>6mCd;wl=vf3RPl)aTEegJSH$%N%O_a5 zYL&G0?ti1b6l{6EwoX_hwkH*5cQcmV0rOGfz|Bz8qW^#+3bjIOFF4ybogvKx{#y>37_FCJ;QdTRM~Pd?eFAuKfOAUmcFVHZkTLwU})Cjk?53v zVqnaTQpL?p-Ot*$!seY(BovTVh;@hEqWFMdmpf%QoDU{>2;3K?3x?5*6}irhtYti9=;{QJ;Og>vh;HYUf#(>?W@^>!YArZ z4@c6>ima5rln?n5MB#j4RADg4&Luy}!uS@gziS*}+KY{+zB?h<`Qq!;Fu%?of(I5^ z;`}Msxrl>XPS(rzNH_{-ubZ;aDIL6EQtmZ2a?*50UvifJ(YaDYC-wh9_{n zs;Fey4)T6^(N27}d$VJO?p_|H^$t#a%#VYF*^&vf^9_!6#=_C%OPVBZ}loedAR z|IDb7_NNuKAnmXknh;StY&=!X%XIUf<#X49wf9{Ohq=6abd}y{`mUxH9I(`quaEj- zf@C0kv&+$vG7LCcoLS~t^|yC#_$C|a`cEXKwYxm7zp%R@1}OkRwY5L^N|?YSDvr)a zvKVFfhUDXu(9UB)A|BV==3-I1)l8F;kiG-4haHnZ2_82E0$_bhjH}SvlhwGxRI!HD zb(aZTl?Z%4ts@Lf*u7O8SdH@%W*@(KDOFfM9(lkX8%+hU^rX9qmhpc~*#D%ibJm?o zK&DWLLUZ}3)fjsy{pnfPI_wWrMVJ^I4wJZ#wtIP|c>zdTg1$kzBO`h_vIs7r^cJ6YT}c% z73JmaXZxXZB4?n?WEB?#w%4<@xITb=_S)_I;9Fjs&DvPS6#hwww+la%ljUto?qtOJ zXVegqcaw{$EUncG-C>3##M$c1<1!m|AK_GfF*KzTuP$vbX>t1|<0UE838(&;UyL1M zZLnio*>4mT4SDPECEvAGO<6ztWW7KSxC+|fdT_2Q?C0&5U$nSz1L7T6`h@lS->m4N zezo>`j1f8_mmh*4Wc%H4vM3Nn9Pn>A~^f#Qd= zXzl?Rnh|!#jB;rQD_|2BKG6OTg7|Rj0!VaoM%(pvjwT-gG>kAhPd6Lbh<04a_|Hp+ z`{y#_&p%#|-)#9_V3qmv16zR=IR9Ax`@G00SvQn@k;mOC|FqpU z*U|s1)+`n+^|~j->gNdqamp|KIa%I`jCcwhC&da>S`Dt)l$V+oQN@2MsP1PRijqi1 zS&KbK8il-zQ)9R@cO_oQ{L!3xkSB6i%&1&+RXz07w_Ow7X}JOqFK5ek{84V**~{3K zh4bah(qg;ZymvkxhjxameI15Njt;4~$XT_*ARhDuYS^XI8>ZusYhuioh!UAC)vQYRr-|9`=W_wv{$Q)y&vI;wFzk9~GEOL-7*vIP8}Jp{pz;BVI{lN}?#_ zg4M#nnp&%&mT_hzO(e9}|I6jJ;nF~F&9QC~mcM57G3~`qXgG3{7RO`e#UD*g<&18( zeNv#>vcK4OK-^Kf>dgMpvh*E9CC%aFisQa_AMw2jiq z{$IvG*2+S@{1oSr6W+O(R1Ib`Z3GJNJAfMN5m*Mk(O(x~sf)ljr}```IeGKbr?{DZ zo~|DZ(!~T!P~rRLh~VSTlhXW1BF6{WUhFN3qSW8@T%f<)z9p=WD?=qxCnf+xJ$f~izT16M9-9+Cgt-}aMUa-7y=1u7; z%rEnZpH=NVa-H=1d;d44v<>R2n(WV@wO2#?h7nBaU701Dtg44LSg+ zJGRtx%Mb5pG_GIf{KcZ}C7-WX(2x$)+6PhrrccdaMOH@%IG?m#BYoRaCt@9kzF?mR z&j!&Z>@k0_U>J&zi_C{~pL2|5Ib# z11WMP(g54(yMFigrZWE1y_PYGo6>0d6)Ked-M9Saf*n#{Pkf)vSw)Ok=DSEUcEQnB zA?$@=k8k0=STJq7hKse>y@+B2)};mrv-#Z(-lp!uCm%eugOrD{~4=3GaAju40kMs zD*-@o1Gc7$w^lw8tBBk_K=_(jn)6NrFxFa9u;MAkX}SP=?3&LK#kw}1KcMnB}Ojj0T3*O9adT&tiV-)K7UO2 zx!U2j3AkQW_KuOlhRq_;mmR!l6*y@O57le^-qEZQtjgWdnSW2qPA|lm|DK2Wd@s2! z+ke-r5A+GJy|DnusRp?0FFXm;xbHIaxv*Cq)_=W#sb!y7I_y!M!41%5N1o@EhFpaa zaD-75pI>M!cYKuu$S{Np#UXJTS&mENeYR^+55|&{h-<+p^Hu3D3%8}$ACwmd4>D_= z$smDv=nW`8U^stjs($78RyTKuA0^ffgx8V*zn zIMC|6YUabLFS>Hm#}_S#wo!miKyR9KiTW$b!p%Ob#G2xi^oIWTtl=hP?1)G-gUNu9 z9CP#fOA@qxhwWeZ=z-Z^l_c-9#Qvd=k+ap5cN1}bEdEBZJJPz8{v5}c(QgtVcF1gl z4qqQ!7vjLZv#cR7y$zLVFtS?nVjIY%QzEhGr2}rKFwY(p;IO4yog6xko6LnE%CBm9 zvvq#yjpc@$NFlTjd7*2x+hz@G(N#Xaa> zLuizObB|z+lg!a<`cwqK4R&e#);brdF5+)4?Sq%e+P-veV2XpGIhe^O0*B@Q_|iP^ z&!9Bt=Z5zs#Kp7w<`-9tco?&9l&CRf8__=GrTsKvb35ue`;oMT6g?VPkSJAs+UzxJ zGF~g$p4R;NLYUGFvt2jrK0cyT8H(V%j_-bdTL>(b05TXw}gXG&r$H-t-Z~` z)VhU6kK>hb4hjtgzL`J;usw?L&Gr_V1vf?`;bF~J#A68?pKROF7*MA0mY(9X_&54d z*Z7L|^* zmJ!P7!xFBJmCL_Q6W^yKA%Qf-)3;km%GyR$z-8`kqMwakPy8)0yznUO&Wr8oYM^ze z=05wa@#kzEv4f+l@l_)I7~OML^D~pGVIU`Zm#uS9bOR~CcPTM5*kHB^;xSAZS$RTY z?`R%pFnrQ2+QJ~QGs{5>=Ku-xkgy{YOli5`&GqWY2k5iyeG+k$xbfgfYZU*i{LWIE z+V|4;Dc>(j#ktowHL>DKA;3D4_RXrh!;qNfqW@>sBa%2ipDU~+_8`de@dhVV@rdE9gJNo%EvA4iYdgUqSnI0x9 z(_+nvgKI(5M!O;`$72lp;`wZ>ey2zuge`PnRQff33S#m4sAY#1VUK{1tsp^%3EnOe z%r$<~8Sh{n@6=6ZsDS7qqx!w28Tqsbn=x==O552SdtJkcRyS<0+&icU?}U;@)n&qbj| z{yKJ;i#Np(Kxh2H?k&?^nxP@I_s1AV+($Hs8NV^BY}HHaeZnXDDbeMx-1Rg=dJig1 zl<9w0V{0vyMfctpWnHm;nD_BVW>dkk5~nE5-H>!t8kF%6ok&bPai;hi8|vlN!*{L0 z{@%5o|AaQm6B;5ZeqA_!*qOxgb3gV)`G+;4iktcfvNs8OClVgQAlT*EJ|$?ePph_m^{h zJ|>?&N``sp21ySGFm^4tRWW603(*XP00<51sYk@^YfenFO7(V#3-4yb)eG-~7fsmg z!;wpwNHQjTdJB?pJ~|_rY&snhDO2hj+g(Y!ka`7M2P(;DHJ@!wwSAVWvHmrG9XIB& zyGd`%nO$`rzm-+a;*It)gOQ2(j{FkY5?QR;TW}NBUzd3JgHx-_u@GD2<(0^yo|%4p z<{}f4^oRA1md={_DCb;$%WPA7d>yaba6U*)GGAZ?8CiqYUbEDEfPMVOw zna#e>Bs+!?#0ZM%zaQGAxxUeDBf=Vr|CO?Tdm6A?c0Dy%byMoCAblOJKqBnhpBR<$ z`eB-b^_#=yzD$gk@YzGt#3$zJj&NJ?oqYiJ&K=IV#9~-+c#UI1z)3qd(2?6bK96XW zD7V0c1(PWvkxHL`KS3_w)8*CtaFeU>FUC)y{laZH_VNo6mMBOm>O&X|lcMHCX3=Ej zHn+fF8#S)z4FMy1_iC$iY5Mb~^tszgo7e?O+w(8qCysw9cofe&1zC!uOftBFg%%Bp zlP(MR=BDv%&aF!}67!p#xkuxRCPYcEk^&o*-T+<_UML^hK?ZP6;C&PSS3W*4~IjU(CCmmA?zor4+Zcryc zq!>-a@L{Nqon~NQ0I!4f-xXaHkAn5HewO>jgAQOY1U}akk$5?Y6-AN*I=2=KDMkc| z8#a2G@;aNhMJNgCA6`0O{Jjr8o#N(Cgy9l}Mhh+x6!h ztStjtI7+)y*^+YeH6QC-)G?WYKqpb^yajbLE+}5UX8y4qk2-NakBHrV##6TJt0c zeaZ}ILjxtF{_oT9hoJ~|Dhkit{3aY@#Z1CfTpe26rqq^FcD8rT7A}TZZuN7BZljRb zM?Z|HLpcxMJtg1d=ne|W2ySr+J>K}!DTo;dp{EG6K+&pH5XS`Z%@9De?;l3akXB$- zHW9RAJq~9$Z1nbnzKl&Yb9WVXVI__WKT2$9FK06W?x)!PCQkX;jnYrtV4iF(7>c9= zR3?Z=e*gVnPmmv(A3qi->__u&0l7*TIP~XF8h9aEdzFfC_^FI&8igy_TzM3ltXozKx zoo|bTrNTLuWK_^=XoyR*&q@D#ChsIQRHiXeHY2*;XSAVi5R3tEO^IaY!= zDOOPoqgw2Mnmw1Ym#@Olf+Bucth8dai*3lMP0|JiwjUwQ2qH-GwQTzGKdFW^C_3B+ zFTTocTrz*y>|K{O4F-#IL^t@Ig{~dVkg+mTpQs1SR&O!9d?5dN2&&V&FhEC?CidBEBU}5rJRtWx# zALe2(vx2jZtsBIXjnyuTQbygvm^ORFXta$ej{I_=Ib_&B_v3SLbgdcBwJC8eV=p2h z^zS?L0npF+U!3{32-hG&QwD=aAR+l|G~>V@*z$ljRCl8h&MJbD{G?X6@j?vnD(wee zAnHkXE|&N?u)zWp1m%=2oD2cSIIH}G<~jR=8LOta50YMYe-5hwJy}5)O)?DN&uj1Q zHaNbxizl0|-n@i-F5bX}Y*Aa;L|3LXq@H^&t91Z)SfmUg&Ivudn;pn8N%;3Zb>=6MX|R^hvkk}kA&_hw9iNz@P6vRTU+0x5J2srua%@tGh(Mnd|cbNs|Ikt&7=@3(?1;9lBtMDv6&Gja71h zEfUBc6}T%9T0qy=g}aLrP6{n_xFD``4&EKUh0FJ}RAhlM?L{kQf}?Q`bbwn`!?F3b zsF@#TYC&QOsN$!K@t^A@gujjOvB02{mxr<@9@Fguq!Q4hj5s53w;HlG<&oQ)WMe`K zX!XaqVvIkUZ&DYhxHBn?)87^R69){$OlH-d^LBTNo>iF$lf?jg!lz3`a0TQ7J!F;@ z6a`F_0-^ibV!EZhf3hrxIz=e(cPzXq`9dt`@DUbcfg`O0Cm40?U~fD8+;^uewMPT+ zJ||t$XMlFk;bnuS)rhul<;A*S2D6mk?PSgG+;^aV^(%Oz4MFq)SbsnuVa7bQ@5l=p zt(Ps9&j~vftwQOObGcZf!XmT#_d`;brbd((yI%bor6l(28(ei-@f5Byi2$j#!9p^* zOoAFFWZ<1stXr#N#ez7hcg(mLJY@3mZlP)pX^q+qcue*9U7j~x`~N|==3eQAzIPit zU`N`06!1jrIWV=vX|~auHW>2$USiW{aB@%AfDQPq^xcw=FVWf0j-xPXBX9wrTSQ2p zGsKrmB0-fhZFU(2TXzW9oYZtx1*)_^jG_8FLf2J2sk(Jt*-U~1ZK~V`wNYFEe7&wL z>H%T-!+D>RGGW4!{6##&=R<&M$8xtfbf%$;i0U_5^}P}m1d>fd!OUM>7g`0l#e8DV zCzUCDo}WJlhL?j#5)OV>dAVS&??05X%;ASd(!Kk(699_&Qb!C9Bj&A%N9rg|h6Btg zE`U_rSj-P|me6dfxrqR@PY)4n361)|QX2u12T)=V=(D=iS3#fW^!bN-@n^C4O8>+o ziIQ!VzHS&6_-oy(j;tmRwgUu*8}A`gt-ueb74!g0j2)yiTbCnmRLiObKjNBaM>qtk zDSieoR*IjClzDRrumv{xv|}6gq=7hU!k0A2h-LBwO|%2|HGkv)D7ot2W&Dg;t81Hp z^P~AI0p6hbz}H1jYQNyTcUoENB~l;BJOOX9Mgq7Xkf>S3J=Ba6$}m1Lh%H5|ID?FxFems{vdEt!A>)FX*E_3Kk>i`9)dR zWPOVx(rz+csvzC6B18V{U=HoiuJWE41jcOQV$&jg-TYrnBB!hP;?#V4^2P(qF~9$V-%+~6tCxSwU-thoIu&(X`XSA?{5p~J z+qyrx3H>RGa)q{EE2GoOcNfu@ zoQMO}s1`Mt%a7CZ6=btlv$7HqANNIcQOH;}m7CkkkKo>N@L8DDU=eHUIM zKx`eX!8~p(onJy@FA}S?klK-6jFDSrUMZE5sI26+GG9v+rO@lu!X?wju%aSm-L=O7 zN5z#w*HpCZ6BBBysy6>M7BL`Iyz%Q;!0I?c19GQJ#o9W&-ngOw8A_1oi{rFs++(yj z%(QW^9jVb}&0!mo0Px2J-W2aD%mjSf<>@!~gh!jg%G#!P@=ICrgitmUopkg z2?dJ+)a<*Gc&GNeMSuilo`9>hu6dj|Y(&QDg*`edO`dl_$?}Iv!PL&HpM#IAO|3&*Fp0&{Q{-Gk94J@ zSOTFt_Nc$vMUljL!UV9ypS$fX$eo`Y2*%=gBt0Z4&d$DpH^McY~ES?XX&;>zWGoFqy4i&1TRClEuhXBqA8*olBfm1p+ zWf9@)(mg7kY$wwP{tuy&3zc^N2B83Ll#)9CO`);Kqhp^?MI^Z}2yiV)-k&B(e;S$< zH-FgKeyf~xjA}HK;!QuaQfDev(!rY1GC+R%C_kE4!tGU~{EHLE?-TwE$j>_5(DOnf z+*2;@V{y0>VKLP}f3Fp-jh4?cHxH01Q<4zwdnjc|WzrgiCS5SM&cq;~2ZIVba}~!I zEZ;Jf$SmaA)OHuul%J}?E~iPfm6U8Erngw7lRR3IUwq@;pq4a33=*J8eYNNlhcr}d z^pnx4tcI)5<7|whVByCb1la90LP{u6(!S;8)!8uvkv1si^`>eb+HbJ3yk9GgcR7ZQ zRoJ!MVjA;nnUUn+`5>O%(bT54n{GgIj$x4B>d6II?Y{xmoml}p>u(S`uz4KdEiTAZ z^4)2z8grZU^IOT;5YI5aVEghE<*B{}cO|rfhHB&W=LXm z@hsu(Pln!;L{tA4rvdh?zFl%L$Es1d#*@oopbg?#gQX8p=ZS4XxPG~>MCLTd-YRKI zH1WXQftb!|^L|mA2>LOm8RG6WEx`lhR8R-3I1K^tEOaIB2l|RF*dinXxsZ*&Nh+Ho z0X=FJH<-l8+A^UWl$q|^t3QUT+!-b7Wu8oqj54>IL+;&d-jMhJ^1*e=nUXLyBCiCR+nmSds9+{L%LYxDIj!y`nNlnp0^=Ike=g)+Aqr1o&!;Mk6ZK&8 zH{)))fzbF-y{qE@_2B-L5sc9Kt52diG@LrTSpffLl+pQ(d%OE^m{ zqnPA3LKueINC4AE1ET)wv+ZDgwtZO~PeC-!^Gp$k`>BVdKnwnS`4-iAGwP*_sClU& z7swg}OPxJ?;GVCjx~m@79Nh$DRC{){H(YJiTG^~&lsKZP@b(q7e?MPr^A3(^L<}-@ z0w@R)&KaVf_Sem8Bt!NTDXIi>o{4UGc3Jyc&c_U>_r=IY`t!nsX^#Br+5Q+Z~tGT7EQeEdSB5ZwibzjlwoCpa|5$5w`}SPw8MOqr`TO zWZDsA#b&ebE-e(!RNDDHE|(D05qB6_zHAofO9(1DkY`;r>Y(Y~z;G%>M+B7v>S#b0 zVVQ=JE33P02&d3{Jb+Fh{tn+vf|nla4cpi9pm|{1+kCV(uCr)m?YreZlIOf4XLkUMbrcsFTd{Gje;r~QU;&*OtVi{i}7S5;(S6D)~A~4$C68?x?X9=fk^T;_Nf~ zgyeL+RD7tz3bOcRI>>=ox^hn=&MYC1l}X-Pz`KSz$nJD}D-Rf>Fj%1jMQv@h!hGwk z9yA8`o{k>%;@=t7ppQ^(4l=~5HdKYqeZ|*F^rVgrJ|v!?x0`?0T34Wf)u&VYdeR*e z2oToPfLG8}x!3R-NK$&_l(!*Fi;maA8@UP<5nI#sy!%% ztc#foEj)0l$q>F`vV%PC7|{}7ro?DB>POcccJUI!hv7DM)&mqH?BuCeZ&mMx?qJZ% z@>WfbN4nh0M4OEWOe12y|K(QSH+p;N&Q+Q^3s8v&;4 zirk4Ov(f7{o>{%*8xQwjIP;LLawae_hUZHIke`Y>10pcjzDg_%U(pSnkKxpjv4Ndp z9ryP-;MNY2u4F?iD}KC6tu6G3g@z(mD7r=Ep6CYHR6pMb7M1!^uukA5%0)S2VH0qeR4++uYjjD~yGYY4r?sh^i@8OtRqqAFuBE-GB_aTruJ#Ub zgH@$+?+!?qwFZ{3BLz=LQrwT6fH^HCvu2!2a@*+2t6!*TFE*@^Z$#&(A{39 zv6N&Ty!PQofpkZugQtWp6bK+p*_!_VhL@Z4q@*gSkctkd$bGB~Ok*QIM)AWUzUd$i zafdKm6Uir233*Sv%nf>(VW2bo{pObNxs30|?N|SNp7jAW3^G#8Z-odta6;>X&^V9h z$yldtT32fA*d>)ZBsA-lCfdg6Z>q`FaWqW}|C_7hAwMly4=Or^m3!?n^b<$jnAebj z47BD-d#Fn|fjmp8NFkTCJAV1@083^I{?5J8OPwyXH;vbnz%7= zBd*)LS1RH1bNUtXi!nA74;enDY*Ni1OC?NJU+W~dY!Ufhe!BRimlwb+V}L2w8y%a z1TGDsK`oETlSb_Qq1-S6NR%@R$Vw%NTYmt|vz!c69^234tXE_}3;jcSEX%WX8Az1k zKev0@16FCDiKBJfFQwZck18ewXTW$x!YGsSn>G`cp=K9^^aHQcu-P9PuXH7%-fP6M zNw4kUx%mFoO`07V^r|y^@#+AZ4hitYm z0a}%Sd^Yl&6_OT%{e1fS;C)ZYZ=bkz-gogphMjdtfQ|nEet=Jy9Dc}1@#*^U(&np1 z_|w|)X=EP{(59x>@7YvH;8_9pLr~ov~1VRY3h%l@_8eDHW8tyJG`(2io!LdDFz+tJwP#57ZP{w_P5Y}cO)$Y#PHarlHDVh-UIv!JLJqVX zUmo85q|q(%aQ5MVOdQ$j&+PuvPj!0gTKcGcylxk!3X$JlHRDo=Yo8@`OT?vZ^(*sF zuk^)^$vyl&(EgUj5~0Z@A~* z<|qZiPKyrK9){=ol!sre6W$1`_yrVKr#=l}pJl(=~#g zF?cf)18Z;G7q)KR*PX^UB(r?nlTnYA&A)(s$-|gsoDF|Ef>k}{w0)<{?$3(bZga>7w)L{ZDOQF#<`Jm3? zQ~Ka(ZrfMznVzP!-wh*N*-Yh zx5?)qbCw%J=k@!FZJ<}_NB)N@P$V<-I;k zn>^FMNIx<=2@EDe0g~%9!28%oy=$cIei7N>BpwJwTH;;ITLKX zf&R-X!Q+K+ zS8+$oKK86U`bkMaMIU#{e$rJ_`+EVn0Ryd*?$0uDw0?XHOuxfJAjtvMmz6dVbql-o zMJ(`L>boEHdW{(utIZH&x0~NL>EU(T1npq*O!lTQs)o^f#$syo>V_a9)tHWy6Z!hN zaZz)XAt+#ZogT1Yn0`|#kz-|2o}VIJghwyPV<@-!bz^>B-R~uMpB>+jI08<556OnL z2am)#J>QnAR9r)ZSa+u5=~Uc~2Ah)wHy+%7o1oiN%QWG}t}Wu(uN~E9)A|_P53>Sw zaVH#|{Ipr6;lt<(@XM`%x`H0RcRX#R5cFq24p1Esg5PH2V=HET7=nG5IGnz$O1z6{ zfa3IzQ=Vt_We+iIqv7%YAXln-lR@3#(q!Sw{h*eNVPW3J4Y#qijXK;&>0rC3FkUQ= z(B@&yhpuYok|`d%hRfd^sy}}TP&sm(LV7<-%_rMNWl=)-#A^;H z9iR11$8*fDu7oCjPvF}muxs1QlxQm7ZWNLT&`7eH&I7^01l<4FFa)X&-*t5ihjQz5w)IqB%PNTNO)JRhAXwmq3P)+X zpf#0!U1106#Si6go*~^aIyc(3QDq_$0>oyHI3LP&8_iO_(alurIhqYL#NQ;{(TOj! zf%WFCV|nl7llg9#lBX|*k$G>#?G4`zOdX15QZeBKBNYHT0tPuuT}wQk9#spxal(-njnpg7xj5;4DAI z;}eZt$2tuj?~BGVGYVUYwjCC0d}z_^2T~FoVL_d9Zm-B5H8Rvv3yU$10Lb zGq@K*Sv$89`EJ4@J*%B3tkQ8h>M^Q;X56O-0yh)3_~y^pBtE*<_}eRO zSMyqUFYexlB=A91UcfKukt*&6thS=kqxhMT`VMoNrQEnfn;I}uOqG}`%H(`o}8 zDw~P%3VUEv<2o*7eH+yh<$z&$;rsS*Sl=B#J0n5V%lmL7<;dpQou*k-2x1B>#b`yZ z6s*5*4x-&^!)ZsCX+52V_m4%?Pygukl|2TPth_V^{@y%vxRO-q#T$*1Up@tK(_Nof z2BV!BiqguX?ja-$e)H}z+T7%b-K|)B-F;ck<+=L;5wUvpM)4PsM560mp*sq9jXw5m zF?fQbCJZv<%lqjJuKT}G{~W^?%`fV)#<<%oSrVecp3nOZo=ZbB;aoh~#);LSyomp$ z=n0pir*kFRnuM<-y3U&5woUBgNJ=R|G>0YK$5S4XdkPGqvTx+C^}|Kzu)9a{LW7;h zX`z6*Mhr({!rB+=QNl*mkx?=AHseb-teqN>I>?gZH23xe(|Ga2lXNrD+Sa zgMop>y#LZfcKbc(72Skq|@oOheK^<;PWJ0Y6f6K*!fZcn+ccjgZ2HkEB?^F9Wx`_d8H!w&>` zD^u!OQcfF%;?o~uszgB0#1Un?mU64H+<{bv+s9+XSATWoUw>uGzX5zc!dIa1 z(T{VWP5^a)M!zfk&>jx^gq}kiGCkUN8-v_L-p7gTijT`y9WW; zTT;lhkkIW8E-uM0Iebf+%RfQpD}Mu}R@)-@qp#{_gPc$ni6hDhkk#4(HwfFRK7k0s zle~J|s{=N!`8daz5q#@e<}2Ptnx|-V;NMD68+Ul)Yc;$YLDjMBR66eVlm*90jD60zFAdp&62|F~e=mknN%8zu z8I~DZCLepR02v#95kH8o5E{3^Gip!Ln*7D~UvcaTlV{sDcp6luSsZpPj$>ezR&t3X z`i;)-U_aM%v98VrQ1wI3fB<9Y0VO2wt=rf&klQkcS=oggD)?!--Q^Gk@RCHw^rtNK(4a})4 zS>F(>ib;0O;|0HBcm^k%;lc<$b>2))!kE8JST%f0>IIPlMO$GKSO)KUo;*H0~`dw0;|Uv7f0|?odW{cEO2s zrUGF!1)~f-pL1|xcO+LdA#_p(xfZPgA0NVdSe3w)iL^>-$y{s;EjoK~xM~^1*r05VPeHt9 z8&AK|KL}cGfA_gC@TooxvG5O2#A=nkyitEX4euF4L!p5(k+pXpO$c1+L`K>`{OXDR zSRX}hCc{>OXk@R%veWdqL5Xn>$W07H;mw-^&xiF!neye`yPw><51q=5o;DaCjaGb$ zr^>{0V)cIZ?;gUn_bG`R%GBqU^Qje3j92TBo|>>b2YP%SFb#f@%Dq|FMF$JL#P6%S zLs}ml>1+jDOFHR8rklUsy5_k3eCTUCyc+YN`r{aeLLerG=bzSzXy84w_ zef>S}*%2M=>{@7CIsrFr9=OvpEydhM2zT+zSu{Y{;HPg+hr>d#oHw>Ii4Ro}>!$X4 zAf*N=iyDBGczlzc^aA3?&v;(V*p;va9&P7XGW*_}5>_<^K5#@#_+CvNOD2ErIXv5bVy)DqQ2# znsc4gcdJ$>?`#z2t3VQOoLSnnxCc;QMJy)=#!~Rqp21eP{TZ#Bztm(r^tE9fE5{~Z zM+LXKsm^9N$I3RfWr+yt>FE0s8aR?|q~}m<@;WAH^dPr^gU90Mn+TiVgv|YR0>E3Cch;Umb5k7@-+m!Q@4ybT)$J0R6rz$BZ@zJ>0O5~a z+yy%H$f@N;MT>|#bXYw65#JlOsFihnQ9qfa25WirqYjU2IqHLk{zI0BB_&A{oEMVv zpi*O94P+zah-V8}6%*&;j?1XWA6aIJujAND{AuO!k@@>fhp!{#p5yy5!OE)MyK|(U z);WGs+ad~*KN7{E%<7Nd-m$xa&-R0RA3BPdZR}x|2KxNP-aYqM8^gt)*S6W7{&bF z=6e}%vuZeWhH~P3LQ*nc}@PFzz&W)pM zdCh3Q2%o3Tsi6B%o|6w~Oyr&fT~!_s>uWnifB=Mk|DETj1L>1Xo>*!$oqDzu@=;A!@fw_M0(`aUKJ$Y$Jc zs4b~bWMLqDZaP!wmQ+tW``7PFDwCJObv9RU9U2tSv#tkDV0r;oOB|Ak-y&K-=$XY~ zST+UA-a&ShZaI#txF|7icXqQ@Qc~c>D%ew4F=kUtyISokJS{SStMF#G z<>5QTc~=GxXvoeDtx8U*pn{cSY*#_F=f9C5bRmL{)KE`2#v7&%;c3?S(e`Q$w#{ zYMSu-=Hi}kaff)(*l_8_yB=4GS9Ww{P$)+TDTKHx^06C2@y@ku>huea|p zVomAJUkJ7K!|3;hFZ_Sl6rRN*nkVQ;n3Q&alGXkgK>AvIVmv zs7RolqMhKEUYiCx@A?PvndOHiptoW#aY8ww=$_5N^wX_a?i< zRC*mMxZV*uA$uPL<;Gxg4Uh%|k^8m({`5VY-Z-QsCn!2=DhzUeHS^#%FAAH0*eOF}VUW~QoJ z8;B8AihliPK@1Io4vvJ{r#FfBL1(<&5Jo`%;&=w@R~h}10Jt2@kGrfiw&jH~FDSK_ z%Z5ZPsWq!6ib-sXoob)l-%&PWsBlX6Jhg$}&+#p3>Cd(__*(!>Yay&7l$Y2{#QCP^ zynkj>;bgv&0$U}-sEVrM}>*pn0y3zmvR+{OnCIT!74Y^ zmX$RUFLduYZfR5~CkBC~*nVA)zbk%F$`V*0y8Tvj557GNonFeS!Kq zX5qOM6yq&?->@&2vwhS8w92;J6Sk!71_#8J6KJ{U0=-46MAF#%(8Xj4L-N9l_rRh< z7vHUisoDBYh!AbOK~2BN<*1w5%+1EgIno9BdtbgeS_OYw7+4JcyjU z8&>gG0IDPvSTU<%-J%f9m!{2c8GCD(qj2obLlUg_THO&e7TM&)4ia^oO+~SqFISC* z4~c6YWk*rl6gK@P=t%HgolO}SOfaxyO=I&vNVr+~e!Ed(AIOW!;!&cmC^i#iK!<1> zHU2BUibu~57PGrr05{I$Pb`*7>Sjzy1y8GC!GaWwh7ERV3kYTavhL%wD2! z;iqQkxg{at=Kiu`PA5M|TiWrhV04s61d$&t8HwM41Fq2?qmLzn6snUdlijYiqdD+uUiE64AsFic0pFOS&i zHqHO>?$e`w6mGKOxT~qngxNApMA!z3$y^Mca(y$>eepG|&sSI6^;V|h@Bte(zI-MF z+I9XxH;vfHYjS4`gPRJlK8c}!VypKxbiZ(j8Bp>b`suRpG>jXV0{&7xx}*9424e|k z)TTx)O1B_qaucaNBN@djqPQmOJ6i=;?{HWB{18`8;>c>L*G>%cpN z2#WQ9Qrbv7Vp>3du`G&)(#<1Q9~(oGa;8eOB*y4Ha^J;@^g|`%-`W!PA5q;+pRG~_ zlW)ghjy#uz#hMc0nTRKnq^6`Bt8_98dJI`!1b+iqBct!Eax|RBTx!=JZ~qcMJ-S_3 zxSCt=<0O;4w)~Ti@O?rPO-?;uj&BUC!c?b)b})P);ElYPk=v*S14^r4l20QGf#s~i zT+mllYqG`9FPK_@c1I>uQ9Me_)cf&W13;y&KMZJ-}u6vx8|Np0qqdu_Sa1~xfz%TZuCG8 zb+<{{wMJ6#yv#O=Dg6(X)ww7k!svtotHDAW)yH;TapNc*dO79&U$imqTWyV&ei0Cg z*2DUw-V%i#@7UG4n_OcP;b?Z6coCDA!x4RiSPc?EmkxgNOhj9WdtujLU+|wfWLyr1 z&R;gP++HpO)Y$BL1|cw_YHZr)Wj_u2cTt%?OD}yQOCv8XyMzOSpv;ea*vmyz3UAUi zlaIYjN%--gm0TaMj$`U7K$uu38P<`5b&msXLh&=eh9qy43f%k$eq z0kC3$r2g=z?lV_+E0zF?uT9AryGPyY)mDSj7X6qV8bLR}3!&X4$8c2tv(6e*8+=v{ zRr0^*l>Q=-G7);FjCrS{#K&+=+j+0pJ*oN}*FG@x1w~#l>+9#!a-Bj^jw&Q*l3&vT z%8M_iKr?zrvrs%5us1vj{`py35)XYIHr$-=99w7oz1{iw1)56`Z`kcUpa|D9!2UYc ztsdhW5C?qkQehJ~wVA{uhy3T-YdTK%&9=ItkkNqWP9g1<7`*9RAb0;KgdDIHqAcmaw~)3?-BjjN zO?}axfKEH>(fgq0e3VChVl(8E{?}*ABad*_w8|YE;fLILj#hM|1yxDGUpcO4`v(); zBZ$qI$u>lLWNQf4ISgP%hvz5j^F;1sBhPE$oUh~3)RIp!Zbxobnx;0MCXwVG{%AoX zDFSu|MNb-sRT%RtxRj>!6ykuiShv6r+F?a~E;H5BukdkY>U*9JLmci&m>R{dB!>`> z!S5+~NA8+q|H+-%Tc<*~vioLSWGnDoaOsoPQAB*Ws+wuETCXf1ve& zY+||7gG)|9eb9kb^Jv1jzkoFmBjivCK$*2@We1H#@cJN0wX{t|-UUlOQ$0bo)fOiL z6ss|e#-37PRkGP%xWFsUUVa{LjTN?d>o4ZC^FrY{Jg|9i+ivo?EQyVGnuNH+4&{^{4E=R09wkoqK_;esuxAQP#zJ$0B%1?C zx9m1|yVgX?*Cde(q*g6=>U8w)WKo|8j^b)1s{J0?A63)MK&-{`5^m>KdAjlUvHYw# zxkzA`NMO|zUz38hfMR8yIco3>U{$tjZ!OCYdi~|;eXiY>q|Byp#%{G$bP^*o71&gA zTN?Jeym8JGU8WcMrP*fO8Oyi!bpky`c`zg3puSL*P@`%e%Rjm4pT z;PMx^QH6vRpTgkP@sU55O4SD)@YzA&<`D*}ZF>D*o_o^TZ6A~)V0Dd>%LJY$L@eF> z6NV=x+HdPgOZnr)%i3Hx>#(S+6h^`FcyMUvyg4TLEQ$MlDlC{;$n^NV1ygYM~qckPtV;EycXKQ@YA?u#$OLT$ZFEJ|EQpMm!z z7C+avhv#xG57XI$?lSz1);$km#AesIEX$X_^4BixbPLCeoP&Jz=Ki~E6aD*)BEw#P zUrSy2wq4m5g1NE|(+TgCcld)+FF1 zuiu#w?NR-34SjBYBCp(}c#@qBYE zi}aN;yOvi6xqkUT4BYL(r#z8o;;oh7jVVmyv3Vlbyd+#Y7bq(roo6sVlAAB- za#JO-+OmqMqJHtm%H#Lwn9QwMT4?d>toY|SDuJN$WZ9-v0nalLn@OoF_%?F!0@|l(U>sKGB5Ux( zEn^(U&1Mqkrr~d+cFC4uvN(4=(M;egLzD}Vc&?b?epw87U-MSVr`Yp=st{HJO2_Z& z+2Wi2ih;kpaLJT;^US31-k$SslT!<_7Ti4$i-9tK{|9mCCl)5reVa#9i>S1JhaX!e zlTb|1rys|;&f3kBSktXPLGfHrB(y$iloTb4(#WH@bLcgIc1J7S#M|oW4=bOVEScwl zWki#S-+W&Z@40&n1>R;fUAEXgn7)KW{v6%V*rPKM71ac?5ZTzFkEoY66BWJw>BXk` zEimN`zV6Q%;MKgNMzG%OIJ9j^92!%3qsXH7Jq4kFvL5ssHKO7L7%)*X-Kiq!^ z{_3e(i75YEzxP53Z*)p;<;h*^X%79x{=nhQxEVLTZ#|aO^loi;%2#ajJ}0q^Y%uCXS<7QX?i>r0#g8UG9I7WDq?`1^} z?WZN@4ePT}>F5Ez(KT(;gTlBxUz4^x+BRoy8a4gqor!YAw-853cit&x7~@}Z1mh^Z z8pb>a9eZFz*bVr{&vUElbCeuvX)Y113ur+-2nG9x60H7VZ&CTO!{AwXz-!L^~Kt>kxJd=NuF_n8P4M9 znTQgYdzeF;ZIkr|od|l33embc?lfjQe?>iwKg+DrH*4`WjrTK(%gxP$X-o%pAI3dl z&=bMIdlo29_lDbXZ>|Cqo2+o(pLpgjowGFlp46~7T!@_gV?1Zf$ll5l<2$yzHk53C z8lVbUI;9c~q8^Wa7jmK2PD>j*FB&WLBb@&`d9dL-JKrA_wBk(?NyCYti>Sm(i(_46ltP zF6H=^zMi6wDev(wiH9Tnij7-8ooYG8-O`f+<0`&LxDOo{rV8_8RA!v&O79R}*K9KS zJ`#S}`hk^e^v}4@WyxB%b%05FOM9m4{G#q!S^-L{U7J<_gR4XMLpSXk=T__GtEvb_ zITydh;5ZVs^5Gp6C*ChXcC%)b1N!Vo#y#N=xf1IBia3ugHX(E%n6%W4 zw!8LDy1cfR zY=5gg&aK7=P4#zc1)#9x35BJ#*O-Mm(8z$119)c*57vTyeNiPf?MP?|J^5*q`aq1R z-%i9rEBNAQ-5{Ri8x(*OTmk+1yWc)&Opfr^)O<4_y}h-|O}hqfO28~yeo2(|#jW=4 zP#$M~dqj?7@I}Mnl7@}>t`=muebrux0R_P&Ix&3*q>k!XHRg!>T+2#YR8<7MQuKp= zwM}w-qz`wa*%%X1BS>Q|G;`N7!3~`%oJ3+d zjn+sgb;jtu=7k5z)362ZPiH--drCQiB9PM_X&o zb9zusER0S+r;MVozwUoSjIjHB@YCDBs&S@f=Hbjljj*U)HRbj)j}1AOVS#!{#;YRt zv``v9jywxgDDYDSWRc@zI8}7^7(n)vJ_ZWM*eM>md`|PibQta&UN=& z>ran&ALgX{_e%xUS*T${@j$mXX61T&&n^A2{u`3@&go^)t1kgTGb%*Aepo3qh!eU* z4YwEOu0w3S*NjjkQoj8ixNn7OX1UB{5%`kY`4&&tZ+*xL6n2;e4KI7z)|L4Ss1ZaP zvi{0dOR3Ixkhl>5>DE4#x6+J$Y|ZwyiH)WoRYahk6(`*HnKoD}K0KRFux902C#923 zv&~Odb<<&?*m&cwM>+N*q&$eP@Vxodu_a3vioBuB7yPb*9&q3qz}4o|{!&-Jsu)?Uzv1|w;bW3 z(Rel0Q6EY;xJ%IgqaLsC?y`deU#@@Y-i7U4~(;{ zEe?_<$wV)!d>mMz$fHD7a06B$v|yJqK*5(?crNLYbFQrg`QH$N%UX_^K~uxqh1wX) z72{}?*o|rGQK!qq-6@%6=|)e@dD|uWc~4ukh~y1|TTZb{rAHWG!%Jw>g4|q+a*a+c z^KuJDDl>w4QnkF3Lg#AU?!9$bvN`ux>_c2R!wQ{IHjZZ{TpddW9T^nu9arKJ72=`! z&Ofa`UJ5{)YaRfvOmob)uidI=anqOoR617nGc)802Dz2rg-7!n@NMQLCtQYkzPj}v zqe`8xra_ywp5}|4NnJ%mY+t>xdEgGvnYwy~1?4liWk;B4`<&NniUqIz39t>zfiLGL zOH;aPy6rEm#xcC$622nBV=j#e<2zG=U4{xSAHKqNUG8phdcyQ;cD*EgEf;&?h9aJ1 zj~~6lG3AVbS}GjAnr7(s#++}#z4#3jd6?SUtp(w3CMxv}zL{0ZjY&JReo`#7DfkVs zZxPzEY`Si`v$z!aTWqPbyFSOiTEobbM7r^#`iAjyN_0^H*Poj;DbfS*HB9#rh`WB} zD^QO3r`wZR^Y9`CENh`JZum7r830LpCEH3POgh_R+w@VxM{#1}UA6WZ!58mr{@4%w zdMs~{Pm9B;@5@r1loXD_UGQ%nVqpUX>N^!NQ%ggELe^yK2%4HM4XT^)&r~WCDlaIK zD(Yu_&l#UIY!Zvd)WNK5rhY8vpX#~Kh!D@lSjj`AlRU2lVG^=wrBB$UW@=sd@GK~w zX`u7kxvo#mUM}d}L>p5m4Q49pg;ajZM3fGh-%m%KW>Wp#e!VZkE~VvaG0Bhk)~Vyq zgM$I(Je2`TyO||5u?D&U|5m9=(y`j|q{w)0w~^AsRlQZnTcE-B*qOM#&cnH(oXcU! z{Mv#WtB;nSQ(?~~A9Y#@QT61{ZaMkvtQLF^GTb;&0hkR@RgiYSd6iHT;E&T+ikPLB z$XtPYQO7G4?Dg7~;V2DOx*gmSam~B%8SJe@`2L)`TQdYmnJOIiF}3MP1D)&Uwx8ON4EI)Y0OuLpMlbGJ=R7Kk$_gBDscholl5`()e{OO6G4-)TI^H+`wukgdRc_H9eF|3Ln_;f~d#IJLre@N8WSikbLXU82@pHiO$KNh)KU{<&8P zv-To`NRyqBMuB7;Z3qWZxm%-ku*nNb5nbv2zC=@;30;$j zxLRDV-uiKeA7m_+-?QezJX0z{5V^V%RPWyZHN`G6@bj$;dzWS3f#Bg}bWO*~OKS@B z#hsW4uudqJN(pFb=~JC&5C%n0IX1ExkgOd#SdTHrRrw0NEa|aqs$syfSh+n{05(*X zza27ht2Z~cf7Ld?rl!RfeKpWF<}(|}`F`~MhS6ydp)B7w7{nmT1ZWUE7@Qk!n{h3G z1nPCppZ4lEpAQEdb=Z!4d1Q*S#OhMqY-h4M-?h9TO0~s5b<#6#t1|mxV&2jKzonVd zh|Czj;jR+iQ{EVUDZ2`*gTvG48efj;l{Zz8;I>IN&=KC99fh{XsUJ$j3tn!B5pF!F z_+)4AYBwMn=Sgz9K%!f`16$4*dRSVVtJK{#b~P2KsaTda_-l8h!hRqWyH$$@4{Rcl znMVRxN^}akcdFrGC?hWYY3s(b;aOXIRJY_cC)F+DFZ#@0`&|w|x8J$)E&36lgwTV|3+Q3i3tUal$oI`3Y?kZNewmmhXL>Mnk>w98p&WX~7wnquv;UC{8Q#bW%eK*mu*w0~3`@jIR!C19_7 zxBQUB)@>XF&72qycFRi-PN?Cv{Q8vHJ95Q0_5uKnQX`og7{ZgQ~eEqn7VpZtPiH=!juT3K@(+g>v8(hh6#X)} zPaqkNp(E*oL&rXy+=4r;Lim7)Cu3c|T7l;_yOHi|pwEsL@RO*+SqU_f8kV0q;o^>=Zxy!-UvvC5l-rBe`uzcNp3iQLH{K61G<%Ok!~zb? zf5mWpW=tx$59P@thxMmKPiC<4wDR(#Ue_;KsIH+b#sNPYvVIxM2w$4?ASG=L2cT?z z#Vj0G+G7MLB6m0E*GoI zf(PZj0FaaoW)3cR0UlgKN3}7HdPg}L9fyh`kf1cMfq;wA=t=u#tpK<=P759sgd{b8 zPoZmjD2~*y0>JO$6R($#HO-cUQpuM<{VI;H2u>q56*Og6y>zMi4P|lsA6|08`nSdR z(RS3u1P@~P#Jv`}LY_dDpOL~!FZ@TSgl&bfr|!}9_fg2<a>n>zW@E-zkt-a*#ToNmc0*t8t%nm1gO#>F=K{1%$=^Wa6{IQPE#rXYU)&w;y;y0 z@57x;W95=?_Dmm&NVp_f@LTx_)bbv{xfNHM*?;t)r27q-q5UKuXlEJ304AG)XRn-C zyu>ce5E)t#J4STWbb<3dv4yaG)X_l3SovL{}27$fobQ)8#b#%Ntc%E#@Mu&#S< zBNWD;GwV%l63_u_z59kctJDjxq*rLBG48U<(mB~Q+ zs?w$$@hyjwqK*2vpJt%gW^ zt9ci|$xjQ%luNi7h6*8&5}x`|_^IM_UEZP$? z8)~Bk44y7IR_J#-%8n>hr+=HZySHTSHioP1EP`w9J&?|LfHRQ#2^X8WJ(&}E}3YG zk=hi{L)gz=Q)a$Ffehz9ypDBo%sy6iym8H|hh(Qq@;dq!I-GQNBACIPWk~)HXUP6! zZ#^KqTmAl`0+q(}1;qg)Ce z8gkKuD3HU`8?3EFV?5IrSeYTH^xqyqA%mP;=ih%*Dl4f0R#52| znhZ|QiVV@jfuE*ifZgr?k%nz^e*;;jQsiQ^SjXQsEl&pU(u)-tQbU0KHyIY4x~D|nY{$?#*yohhm-5#!foot zdC+4p)b$?>H300!iJJ0Z=ojwfWy0*Bg~K{?k92= z8-fJG0Ij4=fN|bed`Lk#;3JiY`cQ-fDPl|{xZq)z-Kn9Mps^(-5^?-CwO^+cd?3L@ z`EPej1v5Z`iQtnqxbmm>-jRsE@?)Tl%1Fe`mv(gP0Gs%c3{U1kN_QB!&`Vrn26nLG z5QC5vRQc@RtcA&YeR20dNpS?2Dzmu`sVcTe_&M>6Jzv*#TGl=N@{ECKb&yn^c;JJ} ztiz9xbBO{-P^KFAG~8k0n?Fk2@XUP!9!x<#*g%FvwNeqlC`AeuvP=V?qzygM8C|T% zkR~Ltjr^SbrzhBS16bnY|{X}Q6FHIT%7`-he<(q2reo)*9RNB2C?*nl!^U)sd~{}uX&AmuwG zh(hcCvy~jA>6oYu2)%s?)Nqjn$%Ux_Brbv&K#ttz|A>r6E(Vcmt(FR{o~IdFbK7lA&o2YcatGf^O%rB)t!;H8NGFjP72lJ`zAUSEp=RYJ3 G1OFd$_Icj` literal 0 HcmV?d00001 diff --git a/src/index.html b/src/index.html index 3a5b0f9..86fbafc 100644 --- a/src/index.html +++ b/src/index.html @@ -3,7 +3,7 @@ - Router Example + Weather Application

diff --git a/src/index.ts b/src/index.ts index 4fe51c7..5c02440 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1 +1,6 @@ +import Weather from "./WeatherApp"; import "./style.css"; + +const rootElement = document.querySelector(".main")! as HTMLElement; +const weather = new Weather(rootElement); +weather.init(); diff --git a/src/style.css b/src/style.css index 9875fa3..821ca8f 100644 --- a/src/style.css +++ b/src/style.css @@ -5,3 +5,99 @@ border: 3px solid #333333; border-radius: 2% 6% 5% 4% / 1% 1% 2% 4%; } + +.city-name-form { + clear: both; + margin-bottom: 20px; +} + +.city-name-input { + width: 280px; +} + +.history-block { + float: right; + text-align: right; +} + +.history-block span { + font-size: 2em; + font-weight: bold; + text-decoration: underline; +} + +.info-block { + float: left; +} + +.info-block div { + display: inline-block; + width: 300px; + vertical-align: top; +} + +#info span { + display: block; + font-size: 2em; + font-weight: bold; +} + +#cityMap { + width: 300px; + vertical-align: top; +} + +.history-block p { + font-size: 2em; +} + +.history-block p:link { + color: blue; +} + +.history-block p:visited { + color: green; +} + +.history-block p:hover { + color: red; + cursor: pointer; +} + +.loader { + width: 32px; + height: 32px; + position: relative; + border-radius: 50%; + color: #ff3d00; + animation: fill 1s ease-in infinite alternate; + margin: 0 auto; +} + +.loader::before, +.loader::after { + content: ""; + position: absolute; + height: 100%; + width: 100%; + border-radius: 50%; + left: 48px; + top: 0; + animation: fill 0.9s ease-in infinite alternate; +} + +.loader::after { + left: auto; + right: 48px; + animation-duration: 1.1s; +} + +@keyframes fill { + 0% { + box-shadow: 0 0 0 2px inset; + } + + 100% { + box-shadow: 0 0 0 10px inset; + } +} diff --git a/tsconfig.json b/tsconfig.json index 362d5d2..50dc53c 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -49,15 +49,15 @@ // "maxNodeModuleJsDepth": 1, /* Specify the maximum folder depth used for checking JavaScript files from 'node_modules'. Only applicable with 'allowJs'. */ /* Emit */ - // "declaration": true /* Generate .d.ts files from TypeScript and JavaScript files in your project. */, + // "declaration": true, /* Generate .d.ts files from TypeScript and JavaScript files in your project. */ // "declarationMap": true, /* Create sourcemaps for d.ts files. */ // "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */ // "sourceMap": true, /* Create source map files for emitted JavaScript files. */ // "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */ // "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If 'declaration' is true, also designates a file that bundles all .d.ts output. */ - // "outDir": "./module" /* Specify an output folder for all emitted files. */, + // "outDir": "./", /* Specify an output folder for all emitted files. */ // "removeComments": true, /* Disable emitting comments. */ - // "noEmit": false /* Disable emitting files from a compilation. */, + "noEmit": true /* Disable emitting files from a compilation. */, // "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */ // "importsNotUsedAsValues": "remove", /* Specify emit/checking behavior for imports that are only used for types. */ // "downlevelIteration": true, /* Emit more compliant, but verbose and less performant JavaScript for iteration. */ diff --git a/webpack.config.js b/webpack.config.js index f73e66c..2e2039e 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -26,6 +26,14 @@ module.exports = { test: /\.css$/i, use: ["style-loader", "css-loader"], }, + { + test: /\.(png|jpe?g|gif|svg)$/i, + use: [ + { + loader: "file-loader?name=images/[name].[ext]", + }, + ], + }, { test: /\.(?:js|mjs|cjs|ts)$/, exclude: /node_modules/, From 4aa09edd9fd9cc519a3a153cd4447d9d495712e9 Mon Sep 17 00:00:00 2001 From: Sergey Akkuratov Date: Wed, 5 Jun 2024 19:55:46 +0300 Subject: [PATCH 2/8] =?UTF-8?q?=D0=A2=D0=B5=D1=81=D1=8B=20=D0=B4=D0=BB?= =?UTF-8?q?=D1=8F=20=D0=BA=D0=BB=D0=B0=D1=81=D1=81=D0=B0=20WeatherApp?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- jest.config.js | 4 ++-- mocks/fileMock.js | 1 + src/WeatherApp.test.ts | 43 ++++++++++++++++++++++++++++++++++++ src/WeatherApp.ts | 49 +++++++++++++++++++++++------------------- 4 files changed, 73 insertions(+), 24 deletions(-) create mode 100644 mocks/fileMock.js create mode 100644 src/WeatherApp.test.ts diff --git a/jest.config.js b/jest.config.js index b64b9a5..3ed4770 100644 --- a/jest.config.js +++ b/jest.config.js @@ -27,7 +27,7 @@ const config = { coverageDirectory: "coverage", // An array of regexp pattern strings used to skip coverage collection - coveragePathIgnorePatterns: ["node_modules", "mocks"], + coveragePathIgnorePatterns: ["node_modules", "mock"], // Indicates which provider should be used to instrument code for coverage // coverageProvider: "babel", @@ -65,7 +65,7 @@ const config = { // forceCoverageMatch: [], // A path to a module which exports an async function that is triggered once before all test suites - // globalSetup: undefined, + // globalSetup: "./src/setup.test.ts", // A path to a module which exports an async function that is triggered once after all test suites // globalTeardown: undefined, diff --git a/mocks/fileMock.js b/mocks/fileMock.js new file mode 100644 index 0000000..9cf3c27 --- /dev/null +++ b/mocks/fileMock.js @@ -0,0 +1 @@ +export default ""; diff --git a/src/WeatherApp.test.ts b/src/WeatherApp.test.ts new file mode 100644 index 0000000..9c6bccc --- /dev/null +++ b/src/WeatherApp.test.ts @@ -0,0 +1,43 @@ +/* eslint-disable dot-notation */ +import fs from "fs"; +import Weather from "./WeatherApp"; +import * as externalRequests from "./externalRequests"; +import { IWeatherData } from "./WeatherRedux/Types"; + +describe("Weather class cehcks", () => { + let weather: Weather; + let rootElement: HTMLDivElement; + + const testWeather: IWeatherData = { + mapData: new Blob([fs.readFileSync("./src/images/oops.png")]), + icon: "04d", + temp: 20.3, + name: "Moscow", + }; + + beforeEach(() => { + rootElement = document.createElement("div"); + weather = new Weather(rootElement); + }); + + it("should create correct object of class Weather", () => { + expect(weather).toBeInstanceOf(Weather); + + expect(weather["rootElement"]).toBe(rootElement); + expect(rootElement.innerHTML).toBe(weather["mainTemplate"]); + expect(weather["cityNameField"]).toBeInstanceOf(HTMLInputElement); + expect(weather["cityNameForm"]).toBeInstanceOf(HTMLFormElement); + expect(weather["loader"]).toBeInstanceOf(HTMLSpanElement); + expect(weather["weatherBlock"]).toBeInstanceOf(HTMLDivElement); + expect(weather["cityMap"]).toBeInstanceOf(HTMLImageElement); + expect(weather["historyBlock"]).toBeInstanceOf(HTMLDivElement); + }); + + it("should do correct initialisation", () => { + jest.spyOn(externalRequests, "getWeatherExternal").mockReturnValueOnce(Promise.resolve(testWeather)); + + weather.init(); + + expect(weather["historyBlock"].innerHTML).toContain("

Moscow

"); + }); +}); diff --git a/src/WeatherApp.ts b/src/WeatherApp.ts index 1656684..ea9d6db 100644 --- a/src/WeatherApp.ts +++ b/src/WeatherApp.ts @@ -19,26 +19,26 @@ export default class Weather {
History:
- + `; - private historyList: string[] = []; - private readonly maxHistorylines: number = 10; - rootElement: HTMLElement; + private readonly rootElement: HTMLElement; + + private readonly historyList: string[] = []; - cityNameField: HTMLInputElement; + private readonly cityNameField: HTMLInputElement; - cityNameForm: HTMLFormElement; + private readonly cityNameForm: HTMLFormElement; - weatherBlock: HTMLDivElement; + private readonly weatherBlock: HTMLDivElement; - historyBlock: HTMLDivElement; + private readonly historyBlock: HTMLDivElement; - cityMap: HTMLImageElement; + private readonly cityMap: HTMLImageElement; - loader: HTMLSpanElement; + private readonly loader: HTMLSpanElement; constructor(rootElement: HTMLElement) { this.rootElement = rootElement; @@ -49,26 +49,34 @@ export default class Weather { this.loader = this.rootElement.querySelector(".loader")!; this.weatherBlock = this.rootElement.querySelector("#info")!; this.cityMap = this.rootElement.querySelector("#cityMap")!; - this.historyBlock = rootElement.querySelector("#history")!; + this.historyBlock = this.rootElement.querySelector("#history")!; } init(): void { + // subscribe for redux state weatherStore.subscribe(this.render.bind(this)); + + // subscribe for submit event this.cityNameForm.addEventListener("submit", (event) => { event.preventDefault(); weatherStore.dispatch(getWeather(this.cityNameField.value)); this.cityNameField.value = ""; }); + // loading history + this.historyList.concat(localStorage.getItem("history")?.split(";") ?? []); + this.historyList.reverse().forEach((cityName) => this.updateHistoryBlock(cityName)); + + // get weather by IP weatherStore.dispatch(getWeather()); } - async render(): Promise { + private async render(): Promise { const state = weatherStore.getState(); switch (state.status) { case AppStatus.ERROR: { this.loader.style.display = "none"; - alert(selectLastError(state)); + this.showErrorMessage(selectLastError(state).message); break; } case AppStatus.LOADING: { @@ -87,7 +95,7 @@ export default class Weather { Couldn't load icon of weather `; } else { - alert("Непрдивиденная ошибка - нет данных о городе!"); + this.showErrorMessage("Непрдивиденная ошибка - нет данных о городе!"); } break; } @@ -96,7 +104,7 @@ export default class Weather { } } - async updateHistoryBlock(cityName: string): Promise { + private async updateHistoryBlock(cityName: string): Promise { if (this.historyList.includes(cityName)) { this.historyList.splice(this.historyList.indexOf(cityName), 1); } @@ -119,15 +127,12 @@ export default class Weather { this.historyList.pop(); this.historyBlock.removeChild(this.historyBlock.lastElementChild!); } - this.setHistory(); - } - - private setHistory(): void { localStorage.setItem("history", this.historyList.join(";")); } - private loadHistory(): void { - this.historyList = localStorage.getItem("history")?.split(";") ?? []; - this.historyList.reverse().forEach((cityName) => this.updateHistoryBlock(cityName)); + // eslint-disable-next-line class-methods-use-this + private showErrorMessage(message: string) { + // eslint-disable-next-line no-alert + alert(message); } } From ca33ff9b7ab3b44a5cc47d329ff13a6374a6a0a2 Mon Sep 17 00:00:00 2001 From: Sergey Akkuratov Date: Wed, 5 Jun 2024 20:58:26 +0300 Subject: [PATCH 3/8] Test commit --- src/WeatherApp.test.ts | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/WeatherApp.test.ts b/src/WeatherApp.test.ts index 9c6bccc..9ccd9ab 100644 --- a/src/WeatherApp.test.ts +++ b/src/WeatherApp.test.ts @@ -3,6 +3,9 @@ import fs from "fs"; import Weather from "./WeatherApp"; import * as externalRequests from "./externalRequests"; import { IWeatherData } from "./WeatherRedux/Types"; +import { weatherStore } from "./WeatherRedux/Store"; +import { ActionTypes, WeatherAction } from "./WeatherRedux/Actions"; +import { Action, Store } from "@reduxjs/toolkit"; describe("Weather class cehcks", () => { let weather: Weather; @@ -15,6 +18,18 @@ describe("Weather class cehcks", () => { name: "Moscow", }; + function storeActionDispatched(type: ActionTypes) { + const { dispatch } = weatherStore; + return new Promise(resolve => { + weatherStore.dispatch = (action: WeatherAction) => { + if (action.type === type) { + resolve(); + } + return dispatch(action); + } + }); + } + beforeEach(() => { rootElement = document.createElement("div"); weather = new Weather(rootElement); From 99a63cacc1c8457428ffa07322103e6c14ec748b Mon Sep 17 00:00:00 2001 From: Sergey Akkuratov Date: Wed, 5 Jun 2024 22:27:05 +0300 Subject: [PATCH 4/8] =?UTF-8?q?=D0=98=D1=81=D0=BF=D1=80=D0=B0=D0=B2=D0=B8?= =?UTF-8?q?=D0=BB=20=D0=B8=D0=BD=D0=B8=D1=86=D0=B8=D0=B0=D0=BB=D0=B8=D0=B7?= =?UTF-8?q?=D0=B0=D1=86=D0=B8=D1=8E=20store=20=D0=B8=20=D0=B7=D0=B0=D0=BF?= =?UTF-8?q?=D1=80=D0=BE=D1=81=20=D0=BA=D0=B0=D1=80=D1=82=D1=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/WeatherApp.test.ts | 37 ++++++++++++++++++++++++------------- src/WeatherApp.ts | 36 ++++++++++++++++++++++++++---------- src/WeatherRedux/Store.ts | 16 +++++++++------- src/WeatherRedux/Types.ts | 3 ++- src/externalRequests.ts | 8 +------- src/index.ts | 3 ++- 6 files changed, 64 insertions(+), 39 deletions(-) diff --git a/src/WeatherApp.test.ts b/src/WeatherApp.test.ts index 9ccd9ab..fb68564 100644 --- a/src/WeatherApp.test.ts +++ b/src/WeatherApp.test.ts @@ -1,38 +1,46 @@ /* eslint-disable dot-notation */ -import fs from "fs"; +import { EnhancedStore, StoreEnhancer, ThunkDispatch, Tuple, UnknownAction } from "@reduxjs/toolkit"; import Weather from "./WeatherApp"; import * as externalRequests from "./externalRequests"; -import { IWeatherData } from "./WeatherRedux/Types"; -import { weatherStore } from "./WeatherRedux/Store"; +import { IWeatherData, WeatherState } from "./WeatherRedux/Types"; +import { getWeatherStore } from "./WeatherRedux/Store"; import { ActionTypes, WeatherAction } from "./WeatherRedux/Actions"; -import { Action, Store } from "@reduxjs/toolkit"; describe("Weather class cehcks", () => { let weather: Weather; let rootElement: HTMLDivElement; const testWeather: IWeatherData = { - mapData: new Blob([fs.readFileSync("./src/images/oops.png")]), + lat: 55.7522, + lon: 37.6156, icon: "04d", temp: 20.3, name: "Moscow", }; - function storeActionDispatched(type: ActionTypes) { - const { dispatch } = weatherStore; - return new Promise(resolve => { - weatherStore.dispatch = (action: WeatherAction) => { + function storeActionDispatched( + store: EnhancedStore< + WeatherState, + WeatherAction, + Tuple<[StoreEnhancer<{ dispatch: ThunkDispatch }>, StoreEnhancer]> + >, + type: ActionTypes + ) { + const { dispatch } = store; + return new Promise((resolve) => { + // eslint-disable-next-line no-param-reassign + store.dispatch = ((action: WeatherAction) => { + dispatch(action); if (action.type === type) { resolve(); } - return dispatch(action); - } + }) as typeof dispatch; }); } beforeEach(() => { rootElement = document.createElement("div"); - weather = new Weather(rootElement); + weather = new Weather(getWeatherStore(), rootElement); }); it("should create correct object of class Weather", () => { @@ -48,11 +56,14 @@ describe("Weather class cehcks", () => { expect(weather["historyBlock"]).toBeInstanceOf(HTMLDivElement); }); - it("should do correct initialisation", () => { + it("should do correct initialisation", async () => { jest.spyOn(externalRequests, "getWeatherExternal").mockReturnValueOnce(Promise.resolve(testWeather)); + jest.spyOn(externalRequests, "getCityName").mockReturnValueOnce(Promise.resolve("Moscow")); weather.init(); + await storeActionDispatched(weather["store"], ActionTypes.GET_WEATHER); + expect(weather["historyBlock"].innerHTML).toContain("

Moscow

"); }); }); diff --git a/src/WeatherApp.ts b/src/WeatherApp.ts index ea9d6db..993f5b6 100644 --- a/src/WeatherApp.ts +++ b/src/WeatherApp.ts @@ -1,7 +1,9 @@ +import { EnhancedStore, StoreEnhancer, ThunkDispatch, Tuple, UnknownAction } from "@reduxjs/toolkit"; import oopsImg from "./images/oops.png"; import { selectCityData, selectLastError } from "./WeatherRedux/Selectors"; -import { getWeather, weatherStore } from "./WeatherRedux/Store"; -import { AppStatus } from "./WeatherRedux/Types"; +import { getWeather } from "./WeatherRedux/Store"; +import { AppStatus, WeatherState } from "./WeatherRedux/Types"; +import { WeatherAction } from "./WeatherRedux/Actions"; export default class Weather { private readonly mainTemplate: string = ` @@ -24,6 +26,19 @@ export default class Weather { private readonly maxHistorylines: number = 10; + private readonly store: EnhancedStore< + WeatherState, + WeatherAction, + Tuple< + [ + StoreEnhancer<{ + dispatch: ThunkDispatch; + }>, + StoreEnhancer, + ] + > + >; + private readonly rootElement: HTMLElement; private readonly historyList: string[] = []; @@ -40,7 +55,8 @@ export default class Weather { private readonly loader: HTMLSpanElement; - constructor(rootElement: HTMLElement) { + constructor(store: EnhancedStore, rootElement: HTMLElement) { + this.store = store; this.rootElement = rootElement; this.rootElement.innerHTML = this.mainTemplate; @@ -54,12 +70,12 @@ export default class Weather { init(): void { // subscribe for redux state - weatherStore.subscribe(this.render.bind(this)); + this.store.subscribe(this.render.bind(this)); // subscribe for submit event this.cityNameForm.addEventListener("submit", (event) => { event.preventDefault(); - weatherStore.dispatch(getWeather(this.cityNameField.value)); + this.store.dispatch(getWeather(this.cityNameField.value)); this.cityNameField.value = ""; }); @@ -68,11 +84,11 @@ export default class Weather { this.historyList.reverse().forEach((cityName) => this.updateHistoryBlock(cityName)); // get weather by IP - weatherStore.dispatch(getWeather()); + this.store.dispatch(getWeather()); } private async render(): Promise { - const state = weatherStore.getState(); + const state = this.store.getState(); switch (state.status) { case AppStatus.ERROR: { this.loader.style.display = "none"; @@ -88,14 +104,14 @@ export default class Weather { const weather = selectCityData(state); if (weather) { await this.updateHistoryBlock(weather.name); - this.cityMap.src = weather.mapData ? URL.createObjectURL(weather.mapData) : oopsImg; + this.cityMap.src = `https://static-maps.yandex.ru/v1?ll=${weather.lon},${weather.lat}&size=300,300&z=8&apikey=21ae407c-6788-4393-bbfa-d1cf463287b0`; this.weatherBlock.innerHTML = `

${weather.name}

Temperature: ${weather.temp} C

Couldn't load icon of weather `; } else { - this.showErrorMessage("Непрдивиденная ошибка - нет данных о городе!"); + this.showErrorMessage("Непрдивиденная ошибка - нет данных с городе!"); } break; } @@ -119,7 +135,7 @@ export default class Weather { const newHistoryLine = document.createElement("p"); newHistoryLine.id = cityName; newHistoryLine.innerHTML = cityName; - newHistoryLine.addEventListener("click", () => weatherStore.dispatch(getWeather(cityName))); + newHistoryLine.addEventListener("click", () => this.store.dispatch(getWeather(cityName))); this.historyBlock.querySelector("span")!.insertAdjacentElement("afterend", newHistoryLine); } diff --git a/src/WeatherRedux/Store.ts b/src/WeatherRedux/Store.ts index 5687d21..3810ea9 100644 --- a/src/WeatherRedux/Store.ts +++ b/src/WeatherRedux/Store.ts @@ -1,16 +1,18 @@ -import { configureStore } from "@reduxjs/toolkit"; +import { Dispatch, configureStore } from "@reduxjs/toolkit"; import { initialState } from "./Types"; import rootReducer from "./Reducer"; -import { errorAction, getWeatherAction, loadingAction } from "./Actions"; +import { WeatherAction, errorAction, getWeatherAction, loadingAction } from "./Actions"; import { getCityName, getWeatherExternal } from "../externalRequests"; -export const weatherStore = configureStore({ - reducer: rootReducer, - preloadedState: initialState, -}); +export function getWeatherStore() { + return configureStore({ + reducer: rootReducer, + preloadedState: initialState, + }); +} export function getWeather(cityName?: string) { - return async (dispatch: typeof weatherStore.dispatch) => { + return async (dispatch: Dispatch) => { dispatch(loadingAction()); try { if (cityName) { diff --git a/src/WeatherRedux/Types.ts b/src/WeatherRedux/Types.ts index 673c3b9..d060478 100644 --- a/src/WeatherRedux/Types.ts +++ b/src/WeatherRedux/Types.ts @@ -5,7 +5,8 @@ export enum AppStatus { } export interface IWeatherData { - mapData?: Blob; + lat: number; + lon: number; icon: string; temp: number; name: string; diff --git a/src/externalRequests.ts b/src/externalRequests.ts index 7a2e781..ab3f757 100644 --- a/src/externalRequests.ts +++ b/src/externalRequests.ts @@ -1,18 +1,12 @@ import { IWeatherData } from "./WeatherRedux/Types"; -export function getMap(lon: number, lat: number): Promise { - return fetch(`https://static-maps.yandex.ru/v1?ll=${lon},${lat}&size=300,300&z=8&apikey=21ae407c-6788-4393-bbfa-d1cf463287b0`).then((response) => - response.blob() - ); -} - export async function getWeatherExternal(cityName: string): Promise { return fetch(`https://api.openweathermap.org/data/2.5/weather?units=metric&q=${cityName}&appid=862e72718d993f06e2ca165446011711`) .then((response) => response.json()) .then(async (data) => { if (data.cod === 200) { return { - mapData: await getMap(data.coord.lon, data.coord.lat), + ...data.coord, icon: data.weather[0].icon, temp: data.main.temp, name: cityName, diff --git a/src/index.ts b/src/index.ts index 5c02440..f28805b 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,6 +1,7 @@ import Weather from "./WeatherApp"; +import { getWeatherStore } from "./WeatherRedux/Store"; import "./style.css"; const rootElement = document.querySelector(".main")! as HTMLElement; -const weather = new Weather(rootElement); +const weather = new Weather(getWeatherStore(), rootElement); weather.init(); From 00a83c3ea9a63e2c244d48eaebeb9ae3cea9d498 Mon Sep 17 00:00:00 2001 From: Sergey Akkuratov Date: Fri, 7 Jun 2024 19:20:30 +0300 Subject: [PATCH 5/8] =?UTF-8?q?=D0=98=D1=81=D0=BF=D1=80=D0=B0=D0=B2=D0=BB?= =?UTF-8?q?=D0=B5=D0=BD=D0=B8=D1=8F=20=D0=B4=D0=BB=D1=8F=20=D1=82=D0=B5?= =?UTF-8?q?=D1=81=D1=82=D0=BE=D0=B2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/WeatherApp.test.ts | 30 +++++++++++++++--------------- src/WeatherRedux/Types.ts | 6 +++--- src/externalRequests.test.ts | 9 +++++++++ 3 files changed, 27 insertions(+), 18 deletions(-) create mode 100644 src/externalRequests.test.ts diff --git a/src/WeatherApp.test.ts b/src/WeatherApp.test.ts index fb68564..d37546a 100644 --- a/src/WeatherApp.test.ts +++ b/src/WeatherApp.test.ts @@ -1,10 +1,10 @@ /* eslint-disable dot-notation */ -import { EnhancedStore, StoreEnhancer, ThunkDispatch, Tuple, UnknownAction } from "@reduxjs/toolkit"; +import { EnhancedStore, StoreEnhancer, ThunkDispatch, Tuple, UnknownAction, Unsubscribe } from "@reduxjs/toolkit"; import Weather from "./WeatherApp"; import * as externalRequests from "./externalRequests"; -import { IWeatherData, WeatherState } from "./WeatherRedux/Types"; +import { AppStatus, IWeatherData, WeatherState } from "./WeatherRedux/Types"; import { getWeatherStore } from "./WeatherRedux/Store"; -import { ActionTypes, WeatherAction } from "./WeatherRedux/Actions"; +import { WeatherAction } from "./WeatherRedux/Actions"; describe("Weather class cehcks", () => { let weather: Weather; @@ -18,23 +18,23 @@ describe("Weather class cehcks", () => { name: "Moscow", }; - function storeActionDispatched( + function weatherIsLoaded( store: EnhancedStore< WeatherState, WeatherAction, Tuple<[StoreEnhancer<{ dispatch: ThunkDispatch }>, StoreEnhancer]> - >, - type: ActionTypes + > ) { - const { dispatch } = store; return new Promise((resolve) => { - // eslint-disable-next-line no-param-reassign - store.dispatch = ((action: WeatherAction) => { - dispatch(action); - if (action.type === type) { + let unsubscribe: Unsubscribe; + const isLoaded = () => { + if (store.getState()?.status === AppStatus.READY) { resolve(); + unsubscribe?.(); } - }) as typeof dispatch; + }; + unsubscribe = store.subscribe(isLoaded); + isLoaded(); }); } @@ -58,12 +58,12 @@ describe("Weather class cehcks", () => { it("should do correct initialisation", async () => { jest.spyOn(externalRequests, "getWeatherExternal").mockReturnValueOnce(Promise.resolve(testWeather)); - jest.spyOn(externalRequests, "getCityName").mockReturnValueOnce(Promise.resolve("Moscow")); + jest.spyOn(externalRequests, "getCityName").mockReturnValueOnce(Promise.resolve(testWeather.name)); weather.init(); - await storeActionDispatched(weather["store"], ActionTypes.GET_WEATHER); + await weatherIsLoaded(weather["store"]); - expect(weather["historyBlock"].innerHTML).toContain("

Moscow

"); + expect(weather["historyBlock"].innerHTML).toContain("Moscow"); }); }); diff --git a/src/WeatherRedux/Types.ts b/src/WeatherRedux/Types.ts index d060478..a46e7a8 100644 --- a/src/WeatherRedux/Types.ts +++ b/src/WeatherRedux/Types.ts @@ -1,7 +1,7 @@ export enum AppStatus { - READY, - LOADING, - ERROR, + READY = "READY", + LOADING = "LOADING", + ERROR = "ERROR", } export interface IWeatherData { diff --git a/src/externalRequests.test.ts b/src/externalRequests.test.ts new file mode 100644 index 0000000..be323eb --- /dev/null +++ b/src/externalRequests.test.ts @@ -0,0 +1,9 @@ +describe("External Requests", () => { + it("should return weather data", async () => { + jest.spyOn(global, "fetch").mockReturnValueOnce( + Promise.resolve({ + json: () => Promise.resolve(weather["Saint Petersburg"]), + }) + ); + }); +}); From ce62ac8e3337820e8076f5ebc8a9f416ace2ec93 Mon Sep 17 00:00:00 2001 From: Sergey Akkuratov Date: Sat, 8 Jun 2024 22:19:16 +0300 Subject: [PATCH 6/8] =?UTF-8?q?=D0=9D=D0=B0=D1=81=D1=82=D1=80=D0=BE=D0=B9?= =?UTF-8?q?=D0=BA=D0=B8=20=D0=B8=20=D1=82=D0=B5=D1=81=D1=82=D1=8B=20=D0=B4?= =?UTF-8?q?=D0=BB=D1=8F=20=D0=B2=D0=BD=D0=B5=D1=88=D0=BD=D0=B8=D1=85=20API?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- FixJSFOMEnvironment.ts | 11 ------ jest.config.js | 2 +- package-lock.json | 68 ++++++++++++++++++++++++++++++++++++ package.json | 1 + src/WeatherApp.ts | 15 +++----- src/WeatherRedux/Reducer.ts | 4 +-- src/externalRequests.test.ts | 67 ++++++++++++++++++++++++++++++++--- src/externalRequests.ts | 4 +-- 8 files changed, 140 insertions(+), 32 deletions(-) delete mode 100644 FixJSFOMEnvironment.ts diff --git a/FixJSFOMEnvironment.ts b/FixJSFOMEnvironment.ts deleted file mode 100644 index 8a366c8..0000000 --- a/FixJSFOMEnvironment.ts +++ /dev/null @@ -1,11 +0,0 @@ -import JSDOMEnvironment from "jest-environment-jsdom"; - -// https://github.com/facebook/jest/blob/v29.4.3/website/versioned_docs/version-29.4/Configuration.md#testenvironment-string -export default class FixJSDOMEnvironment extends JSDOMEnvironment { - constructor(...args: ConstructorParameters) { - super(...args); - - // FIXME https://github.com/jsdom/jsdom/issues/3363 - this.global.structuredClone = structuredClone; - } -} diff --git a/jest.config.js b/jest.config.js index 3ed4770..bd56cef 100644 --- a/jest.config.js +++ b/jest.config.js @@ -153,7 +153,7 @@ const config = { // snapshotSerializers: [], // The test environment that will be used for testing - testEnvironment: "./FixJSFOMEnvironment.ts", + testEnvironment: "jsdom", // Options that will be passed to the testEnvironment // testEnvironmentOptions: {}, diff --git a/package-lock.json b/package-lock.json index 95ba7e7..f14216b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -31,6 +31,7 @@ "husky": "^9.0.11", "jest": "^29.7.0", "jest-environment-jsdom": "^29.7.0", + "jest-fetch-mock": "^3.0.3", "prettier": "^3.2.5", "style-loader": "^3.3.4", "typescript": "^5.4.4", @@ -5423,6 +5424,15 @@ "node": ">=8" } }, + "node_modules/cross-fetch": { + "version": "3.1.8", + "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-3.1.8.tgz", + "integrity": "sha512-cvA+JwZoU0Xq+h6WkMvAUqPEYy92Obet6UdKLfW60qn99ftItKjB5T+BkyWOFWe2pUyfQ+IJHmpOTznqk1M6Kg==", + "dev": true, + "dependencies": { + "node-fetch": "^2.6.12" + } + }, "node_modules/cross-spawn": { "version": "7.0.3", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", @@ -9124,6 +9134,16 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, + "node_modules/jest-fetch-mock": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/jest-fetch-mock/-/jest-fetch-mock-3.0.3.tgz", + "integrity": "sha512-Ux1nWprtLrdrH4XwE7O7InRY6psIi3GOsqNESJgMJ+M5cv4A8Lh7SN9d2V2kKRZ8ebAfcd1LNyZguAOb6JiDqw==", + "dev": true, + "dependencies": { + "cross-fetch": "^3.0.4", + "promise-polyfill": "^8.1.3" + } + }, "node_modules/jest-get-type": { "version": "29.6.3", "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.6.3.tgz", @@ -10624,6 +10644,48 @@ "tslib": "^2.0.3" } }, + "node_modules/node-fetch": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", + "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", + "dev": true, + "dependencies": { + "whatwg-url": "^5.0.0" + }, + "engines": { + "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } + } + }, + "node_modules/node-fetch/node_modules/tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", + "dev": true + }, + "node_modules/node-fetch/node_modules/webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", + "dev": true + }, + "node_modules/node-fetch/node_modules/whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "dev": true, + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, "node_modules/node-forge": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.1.tgz", @@ -11386,6 +11448,12 @@ "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", "dev": true }, + "node_modules/promise-polyfill": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/promise-polyfill/-/promise-polyfill-8.3.0.tgz", + "integrity": "sha512-H5oELycFml5yto/atYqmjyigJoAo3+OXwolYiH7OfQuYlAqhxNvTfiNMbV9hsC6Yp83yE5r2KTVmtrG6R9i6Pg==", + "dev": true + }, "node_modules/prompts": { "version": "2.4.2", "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", diff --git a/package.json b/package.json index 1275065..1268769 100644 --- a/package.json +++ b/package.json @@ -40,6 +40,7 @@ "husky": "^9.0.11", "jest": "^29.7.0", "jest-environment-jsdom": "^29.7.0", + "jest-fetch-mock": "^3.0.3", "prettier": "^3.2.5", "style-loader": "^3.3.4", "typescript": "^5.4.4", diff --git a/src/WeatherApp.ts b/src/WeatherApp.ts index 993f5b6..b471e01 100644 --- a/src/WeatherApp.ts +++ b/src/WeatherApp.ts @@ -89,6 +89,7 @@ export default class Weather { private async render(): Promise { const state = this.store.getState(); + // eslint-disable-next-line default-case switch (state.status) { case AppStatus.ERROR: { this.loader.style.display = "none"; @@ -101,22 +102,16 @@ export default class Weather { } case AppStatus.READY: { this.loader.style.display = "none"; - const weather = selectCityData(state); - if (weather) { - await this.updateHistoryBlock(weather.name); - this.cityMap.src = `https://static-maps.yandex.ru/v1?ll=${weather.lon},${weather.lat}&size=300,300&z=8&apikey=21ae407c-6788-4393-bbfa-d1cf463287b0`; - this.weatherBlock.innerHTML = ` + const weather = selectCityData(state)!; + await this.updateHistoryBlock(weather.name); + this.cityMap.src = `https://static-maps.yandex.ru/v1?ll=${weather.lon},${weather.lat}&size=300,300&z=8&apikey=21ae407c-6788-4393-bbfa-d1cf463287b0`; + this.weatherBlock.innerHTML = `

${weather.name}

Temperature: ${weather.temp} C

Couldn't load icon of weather `; - } else { - this.showErrorMessage("Непрдивиденная ошибка - нет данных с городе!"); - } break; } - default: - break; } } diff --git a/src/WeatherRedux/Reducer.ts b/src/WeatherRedux/Reducer.ts index b6e5efc..3106335 100644 --- a/src/WeatherRedux/Reducer.ts +++ b/src/WeatherRedux/Reducer.ts @@ -7,9 +7,7 @@ export default function rootReducer(state: WeatherState = initialState, action: case ActionTypes.LOADING: return { ...state, status: AppStatus.LOADING }; case ActionTypes.ERROR: { - const newErrors = structuredClone(state.errors); - newErrors.push(action.payload as Error); - return { ...state, status: AppStatus.ERROR, errors: newErrors }; + return { ...state, status: AppStatus.ERROR, errors: [...state.errors, action.payload as Error] }; } case ActionTypes.GET_WEATHER: return { ...state, status: AppStatus.READY, city: action.payload as IWeatherData }; diff --git a/src/externalRequests.test.ts b/src/externalRequests.test.ts index be323eb..63b81fa 100644 --- a/src/externalRequests.test.ts +++ b/src/externalRequests.test.ts @@ -1,9 +1,66 @@ +import { enableFetchMocks } from 'jest-fetch-mock' +import { IWeatherData } from "./WeatherRedux/Types"; +import { getCityName, getWeatherExternal } from "./externalRequests"; + +enableFetchMocks() describe("External Requests", () => { + const testWeather = { + coord: { + lon: 37.6156, + lat: 55.7522, + }, + weather: [ + { + icon: "04d", + }, + ], + main: { + temp: 2, + }, + id: 524901, + name: "Moscow", + cod: 200, + }; + + const errorWeather = { + cood: 400, + message: "TEST ERROR" + } + + const testCity = { + city: "Moscow" + } + + beforeEach(() => { + fetchMock.doMock() + }) + it("should return weather data", async () => { - jest.spyOn(global, "fetch").mockReturnValueOnce( - Promise.resolve({ - json: () => Promise.resolve(weather["Saint Petersburg"]), - }) - ); + fetchMock.mockOnce(JSON.stringify(testWeather)); + + const weatherData: IWeatherData = { + lon: 37.6156, + lat: 55.7522, + icon: "04d", + temp: 2, + name: "Moscow", + }; + + const recivied = await getWeatherExternal("Moscow"); + + expect(recivied).toStrictEqual(weatherData); }); + + it("should return weather data with error", async () => { + fetchMock.mockOnce(JSON.stringify(errorWeather)); + + await expect(getWeatherExternal("Moscow")).rejects.toStrictEqual(Error("Во время получения информации вожникла ошибка: TEST ERROR")); + }); + + it("should return right name", async () => { + fetchMock.mockOnce(JSON.stringify(testCity)); + + const cityRecivied = await getCityName(); + expect(cityRecivied).toStrictEqual("Moscow"); + }) }); diff --git a/src/externalRequests.ts b/src/externalRequests.ts index ab3f757..4613736 100644 --- a/src/externalRequests.ts +++ b/src/externalRequests.ts @@ -3,7 +3,7 @@ import { IWeatherData } from "./WeatherRedux/Types"; export async function getWeatherExternal(cityName: string): Promise { return fetch(`https://api.openweathermap.org/data/2.5/weather?units=metric&q=${cityName}&appid=862e72718d993f06e2ca165446011711`) .then((response) => response.json()) - .then(async (data) => { + .then((data) => { if (data.cod === 200) { return { ...data.coord, @@ -12,7 +12,7 @@ export async function getWeatherExternal(cityName: string): Promise Date: Sat, 8 Jun 2024 22:53:56 +0300 Subject: [PATCH 7/8] =?UTF-8?q?=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=B8=D0=BB?= =?UTF-8?q?=20=D0=BE=D1=81=D1=82=D0=B0=D0=B2=D1=88=D0=B8=D0=B5=D1=81=D1=8F?= =?UTF-8?q?=20=D1=82=D0=B5=D1=81=D1=82=D1=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/WeatherApp.test.ts | 84 +++++++++++++++++++++++++++++++++++++++--- 1 file changed, 78 insertions(+), 6 deletions(-) diff --git a/src/WeatherApp.test.ts b/src/WeatherApp.test.ts index d37546a..bced09c 100644 --- a/src/WeatherApp.test.ts +++ b/src/WeatherApp.test.ts @@ -10,7 +10,7 @@ describe("Weather class cehcks", () => { let weather: Weather; let rootElement: HTMLDivElement; - const testWeather: IWeatherData = { + const weatherMoscow: IWeatherData = { lat: 55.7522, lon: 37.6156, icon: "04d", @@ -18,17 +18,26 @@ describe("Weather class cehcks", () => { name: "Moscow", }; + const weatherSPB: IWeatherData = { + lat: 30, + lon: 20, + icon: "06c", + temp: 10, + name: "SPB", + }; + function weatherIsLoaded( store: EnhancedStore< WeatherState, WeatherAction, Tuple<[StoreEnhancer<{ dispatch: ThunkDispatch }>, StoreEnhancer]> - > + >, + status: AppStatus ) { return new Promise((resolve) => { let unsubscribe: Unsubscribe; const isLoaded = () => { - if (store.getState()?.status === AppStatus.READY) { + if (store.getState()?.status === status) { resolve(); unsubscribe?.(); } @@ -57,13 +66,76 @@ describe("Weather class cehcks", () => { }); it("should do correct initialisation", async () => { - jest.spyOn(externalRequests, "getWeatherExternal").mockReturnValueOnce(Promise.resolve(testWeather)); - jest.spyOn(externalRequests, "getCityName").mockReturnValueOnce(Promise.resolve(testWeather.name)); + jest.spyOn(externalRequests, "getWeatherExternal").mockReturnValueOnce(Promise.resolve(weatherMoscow)); + jest.spyOn(externalRequests, "getCityName").mockReturnValueOnce(Promise.resolve(weatherMoscow.name)); + for(let i=1; i<11;i+=1){ + weather["historyList"].push(`City${i}`); + } + weather.init(); + + await weatherIsLoaded(weather["store"], AppStatus.READY); + + expect(weather["historyBlock"].innerHTML).toContain("Moscow"); + expect(weather["historyBlock"].innerHTML).toContain("City1"); + expect(weather["historyBlock"].innerHTML).toContain("City2"); + expect(weather["historyBlock"].innerHTML).toContain("City3"); + expect(weather["historyBlock"].innerHTML).not.toContain("City10"); + }); + it("should show weather on submit", async () => { + jest.spyOn(externalRequests, "getWeatherExternal").mockReturnValueOnce(Promise.resolve(weatherMoscow)); + jest.spyOn(externalRequests, "getCityName").mockReturnValueOnce(Promise.resolve(weatherMoscow.name)); weather.init(); + + await weatherIsLoaded(weather["store"], AppStatus.READY); + + jest.spyOn(externalRequests, "getWeatherExternal").mockReturnValueOnce(Promise.resolve(weatherSPB)); + + weather["cityNameField"].value = "SPB"; + weather["cityNameForm"].dispatchEvent(new Event("submit")); - await weatherIsLoaded(weather["store"]); + await weatherIsLoaded(weather["store"], AppStatus.LOADING); + await weatherIsLoaded(weather["store"], AppStatus.READY); expect(weather["historyBlock"].innerHTML).toContain("Moscow"); + expect(weather["historyBlock"].innerHTML).toContain("SPB"); + expect(weather["cityNameField"].value).toContain(""); + }); + + it("should correct show errors", async () => { + jest.spyOn(externalRequests, "getWeatherExternal").mockReturnValueOnce(Promise.reject(Error("TEST ERROR"))); + jest.spyOn(externalRequests, "getCityName").mockReturnValueOnce(Promise.resolve(weatherMoscow.name)); + jest.spyOn(window, 'alert').mockImplementation(() => {}); + + weather.init(); + + await weatherIsLoaded(weather["store"], AppStatus.ERROR); + + expect(window.alert).toHaveBeenCalledWith("TEST ERROR"); + }); + + it("should last city on top", async () => { + jest.spyOn(externalRequests, "getWeatherExternal").mockReturnValueOnce(Promise.resolve(weatherMoscow)); + jest.spyOn(externalRequests, "getCityName").mockReturnValueOnce(Promise.resolve(weatherMoscow.name)); + weather.init(); + + await weatherIsLoaded(weather["store"], AppStatus.READY); + + jest.spyOn(externalRequests, "getWeatherExternal").mockReturnValueOnce(Promise.resolve(weatherSPB)); + + weather["cityNameField"].value = "SPB"; + weather["cityNameForm"].dispatchEvent(new Event("submit")); + + await weatherIsLoaded(weather["store"], AppStatus.LOADING); + await weatherIsLoaded(weather["store"], AppStatus.READY); + + jest.spyOn(externalRequests, "getWeatherExternal").mockReturnValueOnce(Promise.resolve(weatherMoscow)); + + weather["historyBlock"].querySelector("p")?.dispatchEvent(new Event("click")); + + await weatherIsLoaded(weather["store"], AppStatus.LOADING); + await weatherIsLoaded(weather["store"], AppStatus.READY); + + expect(weather["historyBlock"].innerHTML.trim()).toBe("History:

Moscow

SPB

"); }); }); From 101a20da7e58f859afa7af413ac69a6744d7191f Mon Sep 17 00:00:00 2001 From: Sergey Akkuratov Date: Sat, 8 Jun 2024 23:00:37 +0300 Subject: [PATCH 8/8] Lint fix --- src/WeatherApp.test.ts | 14 +++++++------- src/externalRequests.test.ts | 18 +++++++++--------- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/src/WeatherApp.test.ts b/src/WeatherApp.test.ts index bced09c..aa8158c 100644 --- a/src/WeatherApp.test.ts +++ b/src/WeatherApp.test.ts @@ -68,7 +68,7 @@ describe("Weather class cehcks", () => { it("should do correct initialisation", async () => { jest.spyOn(externalRequests, "getWeatherExternal").mockReturnValueOnce(Promise.resolve(weatherMoscow)); jest.spyOn(externalRequests, "getCityName").mockReturnValueOnce(Promise.resolve(weatherMoscow.name)); - for(let i=1; i<11;i+=1){ + for (let i = 1; i < 11; i += 1) { weather["historyList"].push(`City${i}`); } weather.init(); @@ -86,11 +86,11 @@ describe("Weather class cehcks", () => { jest.spyOn(externalRequests, "getWeatherExternal").mockReturnValueOnce(Promise.resolve(weatherMoscow)); jest.spyOn(externalRequests, "getCityName").mockReturnValueOnce(Promise.resolve(weatherMoscow.name)); weather.init(); - + await weatherIsLoaded(weather["store"], AppStatus.READY); jest.spyOn(externalRequests, "getWeatherExternal").mockReturnValueOnce(Promise.resolve(weatherSPB)); - + weather["cityNameField"].value = "SPB"; weather["cityNameForm"].dispatchEvent(new Event("submit")); @@ -105,7 +105,7 @@ describe("Weather class cehcks", () => { it("should correct show errors", async () => { jest.spyOn(externalRequests, "getWeatherExternal").mockReturnValueOnce(Promise.reject(Error("TEST ERROR"))); jest.spyOn(externalRequests, "getCityName").mockReturnValueOnce(Promise.resolve(weatherMoscow.name)); - jest.spyOn(window, 'alert').mockImplementation(() => {}); + jest.spyOn(window, "alert").mockImplementation(() => {}); weather.init(); @@ -118,11 +118,11 @@ describe("Weather class cehcks", () => { jest.spyOn(externalRequests, "getWeatherExternal").mockReturnValueOnce(Promise.resolve(weatherMoscow)); jest.spyOn(externalRequests, "getCityName").mockReturnValueOnce(Promise.resolve(weatherMoscow.name)); weather.init(); - + await weatherIsLoaded(weather["store"], AppStatus.READY); jest.spyOn(externalRequests, "getWeatherExternal").mockReturnValueOnce(Promise.resolve(weatherSPB)); - + weather["cityNameField"].value = "SPB"; weather["cityNameForm"].dispatchEvent(new Event("submit")); @@ -136,6 +136,6 @@ describe("Weather class cehcks", () => { await weatherIsLoaded(weather["store"], AppStatus.LOADING); await weatherIsLoaded(weather["store"], AppStatus.READY); - expect(weather["historyBlock"].innerHTML.trim()).toBe("History:

Moscow

SPB

"); + expect(weather["historyBlock"].innerHTML.trim()).toBe('History:

Moscow

SPB

'); }); }); diff --git a/src/externalRequests.test.ts b/src/externalRequests.test.ts index 63b81fa..d97e660 100644 --- a/src/externalRequests.test.ts +++ b/src/externalRequests.test.ts @@ -1,8 +1,8 @@ -import { enableFetchMocks } from 'jest-fetch-mock' +import { enableFetchMocks } from "jest-fetch-mock"; import { IWeatherData } from "./WeatherRedux/Types"; import { getCityName, getWeatherExternal } from "./externalRequests"; -enableFetchMocks() +enableFetchMocks(); describe("External Requests", () => { const testWeather = { coord: { @@ -24,16 +24,16 @@ describe("External Requests", () => { const errorWeather = { cood: 400, - message: "TEST ERROR" - } + message: "TEST ERROR", + }; const testCity = { - city: "Moscow" - } + city: "Moscow", + }; beforeEach(() => { - fetchMock.doMock() - }) + fetchMock.doMock(); + }); it("should return weather data", async () => { fetchMock.mockOnce(JSON.stringify(testWeather)); @@ -62,5 +62,5 @@ describe("External Requests", () => { const cityRecivied = await getCityName(); expect(cityRecivied).toStrictEqual("Moscow"); - }) + }); });