From 4236bae085b2b8ca187167eca2e5a013071b5e1c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=BD=8A=E5=B0=BC=E6=9B=BC?= <97031067+chienniman@users.noreply.github.com> Date: Sun, 10 Dec 2023 14:52:46 +0800 Subject: [PATCH] Site updated: 2023-12-10 14:52:45 --- .../index.html" | 24 +-- .../index.html" | 24 +-- .../index.html" | 24 +-- .../index.html" | 24 +-- .../index.html" | 22 +-- .../index.html" | 22 +-- .../index.html" | 24 +-- .../index.html" | 24 +-- .../index.html" | 24 +-- .../index.html" | 24 +-- .../index.html" | 24 +-- .../index.html" | 22 +-- .../index.html" | 22 +-- .../index.html" | 24 +-- .../index.html" | 24 +-- .../index.html" | 156 ++++++++++++++++++ about/index.html | 24 +-- archives/2023/02/index.html | 22 +-- archives/2023/03/index.html | 22 +-- archives/2023/04/index.html | 22 +-- archives/2023/05/index.html | 22 +-- archives/2023/06/index.html | 22 +-- archives/2023/07/index.html | 22 +-- archives/2023/10/index.html | 22 +-- archives/2023/11/index.html | 22 +-- archives/2023/12/index.html | 126 ++++++++++++++ archives/2023/index.html | 22 +-- archives/2023/page/2/index.html | 22 +-- archives/index.html | 22 +-- archives/page/2/index.html | 22 +-- categories/Backend/index.html | 22 +-- categories/CI-CD/index.html | 22 +-- categories/Diary/index.html | 22 +-- categories/Frontend/index.html | 22 +-- categories/Line-API/index.html | 22 +-- categories/Linux/index.html | 22 +-- categories/index.html | 22 +-- css/index.css | 2 +- css/var.css | 2 +- google0f195ecac6e90bc3.html | 22 +-- images/pubg/pro.jpg | Bin 0 -> 196225 bytes images/pubg/season-stat-27.jpg | Bin 0 -> 20474 bytes index.html | 24 +-- link/index.html | 22 +-- page/2/index.html | 24 +-- portfolio/index.html | 24 +-- search.xml | 57 ++++--- sitemap.xml | 119 +++++++------ tags/AZ-900/index.html | 22 +-- tags/Agile/index.html | 22 +-- tags/Authentication/index.html | 22 +-- tags/Authorization/index.html | 22 +-- tags/Backend/index.html | 22 +-- tags/CI-CD/index.html | 22 +-- tags/CICD-Pipeline/index.html | 22 +-- tags/Diary/index.html | 22 +-- tags/Frontend/index.html | 22 +-- tags/Github-Action/index.html | 22 +-- tags/JWT/index.html | 22 +-- tags/Laravel/index.html | 22 +-- tags/Line-API/index.html | 22 +-- tags/LineBot/index.html | 22 +-- tags/Linux/index.html | 22 +-- tags/Lubuntu/index.html | 22 +-- tags/Monica/index.html | 22 +-- tags/OAuth/index.html | 22 +-- tags/Parcel/index.html | 22 +-- tags/Queue/index.html | 22 +-- tags/RESTful-API/index.html | 22 +-- tags/Swagger/index.html | 22 +-- tags/Youbike-API/index.html | 22 +-- tags/index.html | 22 +-- tags/render/index.html | 22 +-- 73 files changed, 531 insertions(+), 1391 deletions(-) create mode 100644 "(\351\201\212\346\210\262)\347\215\250\350\207\252\346\256\262\346\273\20511\345\220\215PUBG\347\216\251\345\256\266\344\270\246\345\220\203\351\233\236/index.html" create mode 100644 archives/2023/12/index.html create mode 100644 images/pubg/pro.jpg create mode 100644 images/pubg/season-stat-27.jpg diff --git "a/(\345\277\203\345\276\227)Linda-Rising\346\225\217\346\215\267\346\200\235\347\266\255\347\232\204\345\212\233\351\207\217/index.html" "b/(\345\277\203\345\276\227)Linda-Rising\346\225\217\346\215\267\346\200\235\347\266\255\347\232\204\345\212\233\351\207\217/index.html" index b1f5afa7..1cf6b24a 100644 --- "a/(\345\277\203\345\276\227)Linda-Rising\346\225\217\346\215\267\346\200\235\347\266\255\347\232\204\345\212\233\351\207\217/index.html" +++ "b/(\345\277\203\345\276\227)Linda-Rising\346\225\217\346\215\267\346\200\235\347\266\255\347\232\204\345\212\233\351\207\217/index.html" @@ -1,4 +1,4 @@ -(心得)Linda-Rising敏捷思維的力量 | Boris's Blogs

(心得)Linda-Rising敏捷思維的力量

敏捷 vs 固定

實驗中,敏捷思維的學生更願意接受更難的考試、不確定性高的挑戰,固定思維的學生則傾向於證明自己,選擇簡單的考試,力求完美,總結來說,前者願意不斷接受新的挑戰、機會,讓自己成長,後者傾向滿足於過去的成就,力求穩定,實驗的結尾,具備敏捷思維的學生得益於過去的成長,因此有更佳的表現

固定敏捷
能力靜態動態
目的看起來好學習
挑戰避免接受
失敗命中注定獲得資訊
努力因為沒天分專精
態度無助有彈性

Enron 的固定思維

末位淘汰制下,人們破壞別人的專案,使別人看起來很差,讓自己看起來很好,提升自己的排名
,降低被淘汰的風險,但這樣有毒的政策,使公司很快倒閉

西南航空的敏捷思維

西南態度,讓公司成長、學習、變得更好,也鼓勵員工有實驗精神

總結

生而敏捷,不斷地跌倒犯錯成長,成長環境不同,有人在一聲聲稱讚中迷失自我,變得保守,有人在過程中獲得成長,變得敏捷,不斷進步,筆者身邊的小鎮做題家,求學時期即非常優秀,成績名列前茅,擅長社交,通常原生家庭對他們有極高的要求,但人無完人,再優秀也會碰到難關,課業、感情、社交,但自尊心使他們不願意向外界求助,很遺憾地,有人就這樣被困在歷史的夾縫,努力保持過去的榮耀,卻駐足不前,敏捷思維能夠解決這樣的困境,卻不是每個人都可以接受。

文章作者: Boris Chien
文章連結: https://www.boris.idv.tw/(%E5%BF%83%E5%BE%97)Linda-Rising%E6%95%8F%E6%8D%B7%E6%80%9D%E7%B6%AD%E7%9A%84%E5%8A%9B%E9%87%8F/
版權聲明: 本部落格所有文章除特別聲明外,均採用 CC BY-NC-SA 4.0 許可協議。轉載請註明來自 Boris's Blogs

評論
avatar
Boris Chien
網頁前後端開發搭配實作的技術文章與生活紀錄,技術隨筆 https://hackmd.io/@monkeymonkey
Github上找到我
公告
喜歡資訊開發🖥,動手組裝🛠

(心得)Linda-Rising敏捷思維的力量

敏捷 vs 固定

實驗中,敏捷思維的學生更願意接受更難的考試、不確定性高的挑戰,固定思維的學生則傾向於證明自己,選擇簡單的考試,力求完美,總結來說,前者願意不斷接受新的挑戰、機會,讓自己成長,後者傾向滿足於過去的成就,力求穩定,實驗的結尾,具備敏捷思維的學生得益於過去的成長,因此有更佳的表現

固定敏捷
能力靜態動態
目的看起來好學習
挑戰避免接受
失敗命中注定獲得資訊
努力因為沒天分專精
態度無助有彈性

Enron 的固定思維

末位淘汰制下,人們破壞別人的專案,使別人看起來很差,讓自己看起來很好,提升自己的排名
,降低被淘汰的風險,但這樣有毒的政策,使公司很快倒閉

西南航空的敏捷思維

西南態度,讓公司成長、學習、變得更好,也鼓勵員工有實驗精神

總結

生而敏捷,不斷地跌倒犯錯成長,成長環境不同,有人在一聲聲稱讚中迷失自我,變得保守,有人在過程中獲得成長,變得敏捷,不斷進步,筆者身邊的小鎮做題家,求學時期即非常優秀,成績名列前茅,擅長社交,通常原生家庭對他們有極高的要求,但人無完人,再優秀也會碰到難關,課業、感情、社交,但自尊心使他們不願意向外界求助,很遺憾地,有人就這樣被困在歷史的夾縫,努力保持過去的榮耀,卻駐足不前,敏捷思維能夠解決這樣的困境,卻不是每個人都可以接受。

文章作者: Boris Chien
文章連結: https://www.boris.idv.tw/(%E5%BF%83%E5%BE%97)Linda-Rising%E6%95%8F%E6%8D%B7%E6%80%9D%E7%B6%AD%E7%9A%84%E5%8A%9B%E9%87%8F/
版權聲明: 本部落格所有文章除特別聲明外,均採用 CC BY-NC-SA 4.0 許可協議。轉載請註明來自 Boris's Blogs

評論
avatar
Boris Chien
網頁前後端開發搭配實作的技術文章與生活紀錄,技術隨筆 https://hackmd.io/@monkeymonkey
Github上找到我
公告
喜歡資訊開發🖥,動手組裝🛠
\ No newline at end of file +}
\ No newline at end of file diff --git "a/(\345\277\203\345\276\227)\344\270\215\345\220\210\351\202\217\350\274\257\347\232\204\344\270\200\345\221\250/index.html" "b/(\345\277\203\345\276\227)\344\270\215\345\220\210\351\202\217\350\274\257\347\232\204\344\270\200\345\221\250/index.html" index 0d52b0f8..d33f49fd 100644 --- "a/(\345\277\203\345\276\227)\344\270\215\345\220\210\351\202\217\350\274\257\347\232\204\344\270\200\345\221\250/index.html" +++ "b/(\345\277\203\345\276\227)\344\270\215\345\220\210\351\202\217\350\274\257\347\232\204\344\270\200\345\221\250/index.html" @@ -1,4 +1,4 @@ -(心得)不合邏輯的一周 | Boris's Blogs

(心得)不合邏輯的一周

不合邏輯的一周

  • 申請租屋補助不需要房東同意,但如果房東沒有照建物謄本寫合約地址,補件需要房東簽名

  • 隔年會寄稅率變動單給房東,制式租約清楚寫著因稅率變動產生費用由房客承擔

  • 玩 pubg 被莫名其妙的爆炸擊殺,攻擊者顯示為空,伺服器的除錯訊息被印到客戶端,”empty strings table”。

  • 隊友被飢餓者施加負面效果時,我幫忙解除到一半時跑走,變成只能半蹲爬全場,要修復 bug 只能找到同一個隊友重置。

  • 被 C4 飢餓者擊倒後,隊友救我起來,但是負面效果音效沒有解除,整場都是被殭屍抓起來摔的聲音

  • 地圖建模有 bug,住宅區 B 可以在天空趴趴走,而且殭屍抓不到

  • 開發全聯報表發現兩筆資料異常,一家改名稱,另一家倒掉。

  • 有幾家全聯門市庫存是負的

  • 某 Web worker 庫,API 主要兩個方法,start 跟 stop,但是前人傳入完全不相關的 callback ,一行就能解決的功能變成十幾行,而且效率更差。

  • View 完全不切元件,用一大包的參數、嵌套邏輯來判斷,檔案命名與內容幾乎沒有關聯

  • 買飲料時發現喝波霸的吸管變成細的,買飯時 50 號但店員卻拿 49 號的餐給我。

  • 被煙味臭醒,樓下兩層有人手夾著菸伸出窗戶。

  • 椅子整個髒掉,原以為沾到油漆,後發現是舊外套的膠,衛生紙越擦越大片,拿護手霜抹了 2 小時才清乾淨。

  • 隔壁辦公室冷氣壞掉,水像瀑布一樣從天而降,伺服器都濕了,只能搬超大垃圾桶裝水。

  • 大媽理直氣壯的逆向朝我衝來

  • 還是大媽,在平均車速 50、60 的馬路上仰著頭,哼著歌闖紅燈

  • 8:30 找機車位時完全沒有位置

  • 進電梯時被保全拿酒精亂噴,還說等噴完再搭就好

文章作者: Boris Chien
文章連結: https://www.boris.idv.tw/(%E5%BF%83%E5%BE%97)%E4%B8%8D%E5%90%88%E9%82%8F%E8%BC%AF%E7%9A%84%E4%B8%80%E5%91%A8/
版權聲明: 本部落格所有文章除特別聲明外,均採用 CC BY-NC-SA 4.0 許可協議。轉載請註明來自 Boris's Blogs

評論
avatar
Boris Chien
網頁前後端開發搭配實作的技術文章與生活紀錄,技術隨筆 https://hackmd.io/@monkeymonkey
Github上找到我
公告
喜歡資訊開發🖥,動手組裝🛠

(心得)不合邏輯的一周

不合邏輯的一周

  • 申請租屋補助不需要房東同意,但如果房東沒有照建物謄本寫合約地址,補件需要房東簽名

  • 隔年會寄稅率變動單給房東,制式租約清楚寫著因稅率變動產生費用由房客承擔

  • 玩 pubg 被莫名其妙的爆炸擊殺,攻擊者顯示為空,伺服器的除錯訊息被印到客戶端,“empty strings table”。

  • 隊友被飢餓者施加負面效果時,我幫忙解除到一半時跑走,變成只能半蹲爬全場,要修復 bug 只能找到同一個隊友重置。

  • 被 C4 飢餓者擊倒後,隊友救我起來,但是負面效果音效沒有解除,整場都是被殭屍抓起來摔的聲音

  • 地圖建模有 bug,住宅區 B 可以在天空趴趴走,而且殭屍抓不到

  • 開發全聯報表發現兩筆資料異常,一家改名稱,另一家倒掉。

  • 有幾家全聯門市庫存是負的

  • 某 Web worker 庫,API 主要兩個方法,start 跟 stop,但是前人傳入完全不相關的 callback ,一行就能解決的功能變成十幾行,而且效率更差。

  • View 完全不切元件,用一大包的參數、嵌套邏輯來判斷,檔案命名與內容幾乎沒有關聯

  • 買飲料時發現喝波霸的吸管變成細的,買飯時 50 號但店員卻拿 49 號的餐給我。

  • 被煙味臭醒,樓下兩層有人手夾著菸伸出窗戶。

  • 椅子整個髒掉,原以為沾到油漆,後發現是舊外套的膠,衛生紙越擦越大片,拿護手霜抹了 2 小時才清乾淨。

  • 隔壁辦公室冷氣壞掉,水像瀑布一樣從天而降,伺服器都濕了,只能搬超大垃圾桶裝水。

  • 大媽理直氣壯的逆向朝我衝來

  • 還是大媽,在平均車速 50、60 的馬路上仰著頭,哼著歌闖紅燈

  • 8:30 找機車位時完全沒有位置

  • 進電梯時被保全拿酒精亂噴,還說等噴完再搭就好

文章作者: Boris Chien
文章連結: https://www.boris.idv.tw/(%E5%BF%83%E5%BE%97)%E4%B8%8D%E5%90%88%E9%82%8F%E8%BC%AF%E7%9A%84%E4%B8%80%E5%91%A8/
版權聲明: 本部落格所有文章除特別聲明外,均採用 CC BY-NC-SA 4.0 許可協議。轉載請註明來自 Boris's Blogs

評論
avatar
Boris Chien
網頁前後端開發搭配實作的技術文章與生活紀錄,技術隨筆 https://hackmd.io/@monkeymonkey
Github上找到我
公告
喜歡資訊開發🖥,動手組裝🛠
\ No newline at end of file +}
\ No newline at end of file diff --git "a/(\345\277\203\345\276\227)\344\270\215\345\271\270\350\262\267\345\210\260\344\270\203\351\200\262\344\270\203\345\207\272\345\255\220\351\276\215\346\251\237\346\230\257\344\273\200\351\272\274\351\253\224\351\251\227/index.html" "b/(\345\277\203\345\276\227)\344\270\215\345\271\270\350\262\267\345\210\260\344\270\203\351\200\262\344\270\203\345\207\272\345\255\220\351\276\215\346\251\237\346\230\257\344\273\200\351\272\274\351\253\224\351\251\227/index.html" index fcb55ffd..1f32b5d9 100644 --- "a/(\345\277\203\345\276\227)\344\270\215\345\271\270\350\262\267\345\210\260\344\270\203\351\200\262\344\270\203\345\207\272\345\255\220\351\276\215\346\251\237\346\230\257\344\273\200\351\272\274\351\253\224\351\251\227/index.html" +++ "b/(\345\277\203\345\276\227)\344\270\215\345\271\270\350\262\267\345\210\260\344\270\203\351\200\262\344\270\203\345\207\272\345\255\220\351\276\215\346\251\237\346\230\257\344\273\200\351\272\274\351\253\224\351\251\227/index.html" @@ -1,4 +1,4 @@ -(心得)不幸買到七進七出子龍機是什麼體驗 | Boris's Blogs

(心得)不幸買到七進七出子龍機是什麼體驗

在台灣購買桌電有很多管道,但建議盡量到實體通路,購買有保障、評價好的品牌機,價格稍高,但可以省下大把時間,
不需搬著幾公斤的鐵塊到處解被動觸發的子龍任務。

這台電腦在 2020 年初購入,當時的想法很簡單,上課報告寫作業,i5 的舊筆電綽綽有餘,當時對買電腦完全沒概念,只知道 CPU 好就夠了(這不全然正確,想想看在小金龜上裝法拉利的引擎),興致勃勃地上網,在某網購平台看到,電競水冷機 RTX-2060+i7-9700K,竟然只要 3 萬出頭,不管三七二十一就火速下單,送到家剛開機時,七彩奪目的 RGB 燈,半透明側板,未來龐克設計的水冷系統,讓我興奮地整晚睡不著覺。

當時沉浸在刺客教條帶給我的 3A 絕佳體驗,毫無意識到 40%爆擊的背刺正攻向我,那是一個美好的清晨,奇怪,開機怎麼發出 bbb 蜂鳴器的刺耳叫聲,卡在 bios,其實是UEFI,而且讀不到硬碟?花了幾天瞎搞當然是無疾而終,沒備用零件、沒電壓表,如何交叉測試,花了 400 多塊請了個年紀跟我差不多的大學生幫我看,但他拿著無線鍵盤鼓搗了 3 小時只得出可能是主機板的問題的結論,廢話,那我花錢請你來幹嘛,無奈,車馬費還是得付。

撥通原廠電話(不是平台,是負責出貨的廠商),對方態度並不是很好,一副跟他無關的樣子,當時也只能憋著一肚子氣,畢竟這台新機才剛到貨 2 個月,過了一個禮拜接到對方公司的電話,理由十分荒謬,bios 設定有問題,那邊測都沒有問題,得到這樣的答覆我並不意外,畢竟如果承認並被客人錄音,可能會導致公司的商譽損失,但不斷推卸責任並且拒絕認錯的態度真的讓人觀感非常差。

摸摸鼻子就認了,能用這種價格享受”電競級”桌電,已經很划算,當年底,再次壞去,這次是不斷開機、斷電的無限輪迴,黑貓物流很快就載回去原廠,猜猜這次給的理由是甚麼? “完全沒有問題!這邊測都可以正常開機”,氣到直接笑出來,反問要不要把秀斗的影片傳給他看,毫不意外的客服持續跳針,像留聲機一樣,重複應著荒謬又諷刺的”官方說法”。

到這裡已經對這家公司不抱任何期待,先不說他們修完電腦還忘記幫我安裝作業系統,又噴了一筆微軟授權費,就這樣風平浪靜地度過了一年,還記得那是個炎熱的下午,此起彼落的蜂鳴聲呼應著窗外的蟬鳴,又來,有完沒完,也知道結局跟理由是甚麼了,唯一不同的是被另外收了 1000 元的”檢測費”,到目前為止維修這台電腦的成本已經可以購買上一個檔次的電腦了,只希望不要再出問題。
玩遊戲到一半畫面卡住,上網查可能是記憶體接觸不良,自己隨便弄重裝好了就不理了,繼續用,昨天,跑程式有點卡頓,記憶體只剩一條在運作,Windows 大量的背景程式讓 Ram 飆到 80、90%,拆開主機滿滿的灰塵彷彿濃霧散出,決定花錢消災,請人幫我清潔、上油,又能動了。

低於市場行情的 3C 設備真的要慎選,平板、電腦、手機有所謂福利品,電腦零件同樣也有,價格甚至不到正常品的一半,惡劣一點的拿伺服器拆下來的垃圾重組,外行人也看不出來,整包算下來真的不划算,羊毛出在羊身上,價格便宜是犧牲品質、使用者體驗、賣家商譽換出來的,題外話,就算大品牌的筆電故障率不見得比較低,例如台灣的 A 開頭品牌,滔滔不絕的皇家子龍任務災情慘重,奇怪,美國 A 開頭有水果在上面的故障率就很低。

文章作者: Boris Chien
文章連結: https://www.boris.idv.tw/(%E5%BF%83%E5%BE%97)%E4%B8%8D%E5%B9%B8%E8%B2%B7%E5%88%B0%E4%B8%83%E9%80%B2%E4%B8%83%E5%87%BA%E5%AD%90%E9%BE%8D%E6%A9%9F%E6%98%AF%E4%BB%80%E9%BA%BC%E9%AB%94%E9%A9%97/
版權聲明: 本部落格所有文章除特別聲明外,均採用 CC BY-NC-SA 4.0 許可協議。轉載請註明來自 Boris's Blogs

評論
avatar
Boris Chien
網頁前後端開發搭配實作的技術文章與生活紀錄,技術隨筆 https://hackmd.io/@monkeymonkey
Github上找到我
公告
喜歡資訊開發🖥,動手組裝🛠

(心得)不幸買到七進七出子龍機是什麼體驗

在台灣購買桌電有很多管道,但建議盡量到實體通路,購買有保障、評價好的品牌機,價格稍高,但可以省下大把時間,
不需搬著幾公斤的鐵塊到處解被動觸發的子龍任務。

這台電腦在 2020 年初購入,當時的想法很簡單,上課報告寫作業,i5 的舊筆電綽綽有餘,當時對買電腦完全沒概念,只知道 CPU 好就夠了(這不全然正確,想想看在小金龜上裝法拉利的引擎),興致勃勃地上網,在某網購平台看到,電競水冷機 RTX-2060+i7-9700K,竟然只要 3 萬出頭,不管三七二十一就火速下單,送到家剛開機時,七彩奪目的 RGB 燈,半透明側板,未來龐克設計的水冷系統,讓我興奮地整晚睡不著覺。

當時沉浸在刺客教條帶給我的 3A 絕佳體驗,毫無意識到 40%爆擊的背刺正攻向我,那是一個美好的清晨,奇怪,開機怎麼發出 bbb 蜂鳴器的刺耳叫聲,卡在 bios,其實是UEFI,而且讀不到硬碟?花了幾天瞎搞當然是無疾而終,沒備用零件、沒電壓表,如何交叉測試,花了 400 多塊請了個年紀跟我差不多的大學生幫我看,但他拿著無線鍵盤鼓搗了 3 小時只得出可能是主機板的問題的結論,廢話,那我花錢請你來幹嘛,無奈,車馬費還是得付。

撥通原廠電話(不是平台,是負責出貨的廠商),對方態度並不是很好,一副跟他無關的樣子,當時也只能憋著一肚子氣,畢竟這台新機才剛到貨 2 個月,過了一個禮拜接到對方公司的電話,理由十分荒謬,bios 設定有問題,那邊測都沒有問題,得到這樣的答覆我並不意外,畢竟如果承認並被客人錄音,可能會導致公司的商譽損失,但不斷推卸責任並且拒絕認錯的態度真的讓人觀感非常差。

摸摸鼻子就認了,能用這種價格享受"電競級"桌電,已經很划算,當年底,再次壞去,這次是不斷開機、斷電的無限輪迴,黑貓物流很快就載回去原廠,猜猜這次給的理由是甚麼? “完全沒有問題!這邊測都可以正常開機”,氣到直接笑出來,反問要不要把秀斗的影片傳給他看,毫不意外的客服持續跳針,像留聲機一樣,重複應著荒謬又諷刺的"官方說法"。

到這裡已經對這家公司不抱任何期待,先不說他們修完電腦還忘記幫我安裝作業系統,又噴了一筆微軟授權費,就這樣風平浪靜地度過了一年,還記得那是個炎熱的下午,此起彼落的蜂鳴聲呼應著窗外的蟬鳴,又來,有完沒完,也知道結局跟理由是甚麼了,唯一不同的是被另外收了 1000 元的"檢測費",到目前為止維修這台電腦的成本已經可以購買上一個檔次的電腦了,只希望不要再出問題。
玩遊戲到一半畫面卡住,上網查可能是記憶體接觸不良,自己隨便弄重裝好了就不理了,繼續用,昨天,跑程式有點卡頓,記憶體只剩一條在運作,Windows 大量的背景程式讓 Ram 飆到 80、90%,拆開主機滿滿的灰塵彷彿濃霧散出,決定花錢消災,請人幫我清潔、上油,又能動了。

低於市場行情的 3C 設備真的要慎選,平板、電腦、手機有所謂福利品,電腦零件同樣也有,價格甚至不到正常品的一半,惡劣一點的拿伺服器拆下來的垃圾重組,外行人也看不出來,整包算下來真的不划算,羊毛出在羊身上,價格便宜是犧牲品質、使用者體驗、賣家商譽換出來的,題外話,就算大品牌的筆電故障率不見得比較低,例如台灣的 A 開頭品牌,滔滔不絕的皇家子龍任務災情慘重,奇怪,美國 A 開頭有水果在上面的故障率就很低。

文章作者: Boris Chien
文章連結: https://www.boris.idv.tw/(%E5%BF%83%E5%BE%97)%E4%B8%8D%E5%B9%B8%E8%B2%B7%E5%88%B0%E4%B8%83%E9%80%B2%E4%B8%83%E5%87%BA%E5%AD%90%E9%BE%8D%E6%A9%9F%E6%98%AF%E4%BB%80%E9%BA%BC%E9%AB%94%E9%A9%97/
版權聲明: 本部落格所有文章除特別聲明外,均採用 CC BY-NC-SA 4.0 許可協議。轉載請註明來自 Boris's Blogs

評論
avatar
Boris Chien
網頁前後端開發搭配實作的技術文章與生活紀錄,技術隨筆 https://hackmd.io/@monkeymonkey
Github上找到我
公告
喜歡資訊開發🖥,動手組裝🛠
\ No newline at end of file +}
\ No newline at end of file diff --git "a/(\345\277\203\345\276\227)\346\210\221\347\232\204\347\254\254\344\270\200\345\217\260Lubuntu\347\255\206\351\233\273/index.html" "b/(\345\277\203\345\276\227)\346\210\221\347\232\204\347\254\254\344\270\200\345\217\260Lubuntu\347\255\206\351\233\273/index.html" index 95c2d77f..abf01ee3 100644 --- "a/(\345\277\203\345\276\227)\346\210\221\347\232\204\347\254\254\344\270\200\345\217\260Lubuntu\347\255\206\351\233\273/index.html" +++ "b/(\345\277\203\345\276\227)\346\210\221\347\232\204\347\254\254\344\270\200\345\217\260Lubuntu\347\255\206\351\233\273/index.html" @@ -1,4 +1,4 @@ -(心得)我的第一台Lubuntu筆電 | Boris's Blogs

(心得)我的第一台Lubuntu筆電

前言

以前就想要安裝Linux作業系統,長期習慣Windows介面的我遲未行動,一部分是因為許多Steam遊戲不支援,
舊筆電(使用5年)出現花屏,可能是顯示卡、螢幕問題,拿去修理效益比實在不大,但又有外出攜帶需求,結合價格、使用
頻率、開發需求、硬體規格等多方要素,2021年購入這台不到一萬的迷你筆電。

規格

  • 處理器:IntelR Celeron N4020 Processor 1.1 GHz (4M Cache, up to 2.8 GHz)
  • 記憶體(內建/最大):4GB DDR4
  • 硬碟:64G EMMC

大小跟平板差不多(11.6”HD霧面寬螢幕),重量1.05KG,適合外出,預設安裝Windows10 S模式(只允許 Microsoft Store 上提供的應用程式),整體來說開機相當快速,能上網、文書處理、前後端開發、跑資料庫,不過有時會黑屏閃退,這台小筆電開太多Chrome分頁,CPU就會飆到80、90%,所以桌機就漸漸取代它,直到最近整理時,打算安裝輕量級的Ubuntu版本,使其起死回生。

Lubuntu

Linux有許多版本,適合桌面使用的Ubuntu,常用於伺服器和商業環境,許多其他Linux上游的Debian,CentOS等。
Ubuntu又有許多分支,UbuntuKylin、Kubuntu、Xubuntu、Edubuntu、Mythbuntu,本機選用的Lubuntu輕量、快速,適合老舊機型、規格低下的筆電。

映像檔

先到官方網站下載映像檔,

燒錄開機碟


使用rufus製作開機碟
1.裝置,選擇外接硬碟(USB)
2.開機模式,選擇剛剛下載的Lubuntu映像檔
3.資料分割方式,依照UEFI、BIOS選擇

UEFI(統一可擴充韌體接口)開機

Asus筆電開機時長按F2,進入UEFI,開機順序更改為USB開機

啟動安裝

grub 啟動畫面。
1.安裝,選擇Try 或 Install Lubuntu。
2.顯卡問題,比如較新的 nvidia 卡,選擇safe graphics。
3.測試ram,選擇Test memory。

實時預覽

啟動後,探索 Lubuntu 並確保所有硬體都能正常工作。準備好後,雙擊桌面左上角的圖標

設定

位置

鍵盤

切割硬碟


刪除磁盤。格式化磁盤,請備份所有重要資料。

密碼配置

最後配置檢查

重新啟動,大功告成

參考資料&圖片

lubuntu手冊

文章作者: Boris Chien
文章連結: https://www.boris.idv.tw/(%E5%BF%83%E5%BE%97)%E6%88%91%E7%9A%84%E7%AC%AC%E4%B8%80%E5%8F%B0Lubuntu%E7%AD%86%E9%9B%BB/
版權聲明: 本部落格所有文章除特別聲明外,均採用 CC BY-NC-SA 4.0 許可協議。轉載請註明來自 Boris's Blogs

評論

(心得)我的第一台Lubuntu筆電

前言

以前就想要安裝Linux作業系統,長期習慣Windows介面的我遲未行動,一部分是因為許多Steam遊戲不支援,
舊筆電(使用5年)出現花屏,可能是顯示卡、螢幕問題,拿去修理效益比實在不大,但又有外出攜帶需求,結合價格、使用
頻率、開發需求、硬體規格等多方要素,2021年購入這台不到一萬的迷你筆電。

規格

  • 處理器:IntelR Celeron N4020 Processor 1.1 GHz (4M Cache, up to 2.8 GHz)
  • 記憶體(內建/最大):4GB DDR4
  • 硬碟:64G EMMC

大小跟平板差不多(11.6"HD霧面寬螢幕),重量1.05KG,適合外出,預設安裝Windows10 S模式(只允許 Microsoft Store 上提供的應用程式),整體來說開機相當快速,能上網、文書處理、前後端開發、跑資料庫,不過有時會黑屏閃退,這台小筆電開太多Chrome分頁,CPU就會飆到80、90%,所以桌機就漸漸取代它,直到最近整理時,打算安裝輕量級的Ubuntu版本,使其起死回生。

Lubuntu

Linux有許多版本,適合桌面使用的Ubuntu,常用於伺服器和商業環境,許多其他Linux上游的Debian,CentOS等。
Ubuntu又有許多分支,UbuntuKylin、Kubuntu、Xubuntu、Edubuntu、Mythbuntu,本機選用的Lubuntu輕量、快速,適合老舊機型、規格低下的筆電。

映像檔

先到官方網站下載映像檔,

燒錄開機碟


使用rufus製作開機碟
1.裝置,選擇外接硬碟(USB)
2.開機模式,選擇剛剛下載的Lubuntu映像檔
3.資料分割方式,依照UEFI、BIOS選擇

UEFI(統一可擴充韌體接口)開機

Asus筆電開機時長按F2,進入UEFI,開機順序更改為USB開機

啟動安裝

grub 啟動畫面。
1.安裝,選擇Try 或 Install Lubuntu。
2.顯卡問題,比如較新的 nvidia 卡,選擇safe graphics。
3.測試ram,選擇Test memory。

實時預覽

啟動後,探索 Lubuntu 並確保所有硬體都能正常工作。準備好後,雙擊桌面左上角的圖標

設定

位置

鍵盤

切割硬碟


刪除磁盤。格式化磁盤,請備份所有重要資料。

密碼配置

最後配置檢查

重新啟動,大功告成

參考資料&圖片

lubuntu手冊

文章作者: Boris Chien
文章連結: https://www.boris.idv.tw/(%E5%BF%83%E5%BE%97)%E6%88%91%E7%9A%84%E7%AC%AC%E4%B8%80%E5%8F%B0Lubuntu%E7%AD%86%E9%9B%BB/
版權聲明: 本部落格所有文章除特別聲明外,均採用 CC BY-NC-SA 4.0 許可協議。轉載請註明來自 Boris's Blogs

評論
\ No newline at end of file +}
\ No newline at end of file diff --git "a/(\345\277\203\345\276\227)\350\200\203\345\217\226AZ-900\345\277\203\345\276\227\345\210\206\344\272\253/index.html" "b/(\345\277\203\345\276\227)\350\200\203\345\217\226AZ-900\345\277\203\345\276\227\345\210\206\344\272\253/index.html" index 8e3c917c..e51ab1ef 100644 --- "a/(\345\277\203\345\276\227)\350\200\203\345\217\226AZ-900\345\277\203\345\276\227\345\210\206\344\272\253/index.html" +++ "b/(\345\277\203\345\276\227)\350\200\203\345\217\226AZ-900\345\277\203\345\276\227\345\210\206\344\272\253/index.html" @@ -123,7 +123,7 @@ } } detectApple() - })(window)

(心得)考取AZ-900心得分享

筆者於2022/10/29通過AZ900,在此分享,先前在FB看到大推Azure廣告,本身雖以軟體開發為主,但對雲端也深感興趣。

流程

1.聽完線上講座免費拿考試卷 / 自費購買($75美元,印象中)
2.報名線上/實體,自己是去聯成電腦考試
3.考試前要先拍證件照
4.被帶進小房間考試,全程後面有考官盯著
5.印象中寫了30分鐘就交了,當場就知道分數

如何準備

1.寫考古題再去背概念(畫心智圖)
2.youtube/微軟 Doc 掃一次
3.英文準備

範例

考題幾乎都是一個概念的比較,例如混合雲、公共雲、私有雲差別應用,很快就能判斷,但是
中英文翻譯落差,第一眼看到題目可能會愣住,因此建議讀文件&考古都使用英文

選擇題-官方例題

組織會使用哪一種雲端方法來充分利用內部部署技術投資,並在兩個環境之間共用資料和應用程式?

A. 公用雲端
B. 私人雲端
C. 混合式雲端
D. 內部部署資料中心

混合雲:

控制——您的組織可以為需要低延遲的敏感資產或工作負載維護私有基礎架構。
靈活性——您可以在需要時利用公共雲中的額外資源。
成本效益——通過擴展到公共雲的能力,您只需在需要時為額外的計算能力付費。
輕鬆— 過渡到云不必費力,因為您可以逐步遷移 — 隨著時間的推移逐步分階段遷移工

公共雲

公共雲是最常見的雲計算部署類型。雲資源(如服務器和存儲)由第三方雲服務提供商擁有和運營,並通過互聯網交付。使用公共雲,所有硬件、軟件和其他支持基礎設施都由雲提供商擁有和管理。Microsoft Azure 是公共雲的一個示例。

在公共雲中,您與其他組織或云“租戶”共享相同的硬件、存儲和網絡設備,並使用 Web 瀏覽器訪問服務和管理您的帳戶。公共雲部署經常用於提供基於 Web 的電子郵件、在線辦公應用程序、存儲以及測試和開發環境。

優勢:
降低成本——無需購買硬件或軟件,您只需為使用的服務付費。
無需維護——您的服務提供商提供維護。
近乎無限的可擴展性——按需資源可滿足您的業務需求。
高可靠性——龐大的服務器網絡確保不會出現故障。

私有云由一個企業或組織專門使用的雲計算資源組成。私有云可以物理地位於您組織的現場數據中心,也可以由第三方服務提供商託管。但在私有云中,服務和基礎設施始終在私有網絡上維護,硬件和軟件專門用於您的組織。

通過這種方式,私有云可以讓組織更輕鬆地自定義其資源以滿足特定的 IT 要求。私有云通常被政府機構、金融機構和任何其他具有關鍵業務運營的中大型組織所使用,這些組織尋求增強對環境的控制。

私有雲:

更大的靈活性——您的組織可以自定義其云環境以滿足特定的業務需求。
更多控制——資源不與他人共享,因此可以實現更高級別的控制和隱私。
更高的可擴展性——與本地基礎設施相比,私有云通常提供更高的可擴展性。

解答

答案是 C. 混合式雲端。

推薦資源

Microsoft AZ-900 Exam免費考古題

總結

AZ-900都是以簡單快速記憶為主,不需要深度記憶與推理,廣度大於深度,快速掃過的效益比才是最高的,時間不夠可以直接刷考古題,不建議找太舊的。

可參考當次的考試指南,這樣比較有方向,網路考古題有些答案是錯的,而且分歧極大,遇到這種題目都建議直接找官方文檔。

不過要是像我一樣前天晚上才準備了話建議是直接pass,還記得走出考場的時候只花了一半時間,壓線通過,監考官還疑惑地問說今天怎麼這麼多人都來考,完成後必須在登記表上
簽退,掃了一下當天大概有4個來考,並不是每一位都通過。

https://azure.microsoft.com/en-gb/resources/cloud-computing-dictionary/what-is-iaas/#faq

文章作者: Boris Chien
文章連結: https://www.boris.idv.tw/(%E5%BF%83%E5%BE%97)%E8%80%83%E5%8F%96AZ-900%E5%BF%83%E5%BE%97%E5%88%86%E4%BA%AB/
版權聲明: 本部落格所有文章除特別聲明外,均採用 CC BY-NC-SA 4.0 許可協議。轉載請註明來自 Boris's Blogs

評論

(心得)考取AZ-900心得分享

筆者於2022/10/29通過AZ900,在此分享,先前在FB看到大推Azure廣告,本身雖以軟體開發為主,但對雲端也深感興趣。

流程

1.聽完線上講座免費拿考試卷 / 自費購買($75美元,印象中)
2.報名線上/實體,自己是去聯成電腦考試
3.考試前要先拍證件照
4.被帶進小房間考試,全程後面有考官盯著
5.印象中寫了30分鐘就交了,當場就知道分數

如何準備

1.寫考古題再去背概念(畫心智圖)
2.youtube/微軟 Doc 掃一次
3.英文準備

範例

考題幾乎都是一個概念的比較,例如混合雲、公共雲、私有雲差別應用,很快就能判斷,但是
中英文翻譯落差,第一眼看到題目可能會愣住,因此建議讀文件&考古都使用英文

選擇題-官方例題

組織會使用哪一種雲端方法來充分利用內部部署技術投資,並在兩個環境之間共用資料和應用程式?

A. 公用雲端
B. 私人雲端
C. 混合式雲端
D. 內部部署資料中心

混合雲:

控制——您的組織可以為需要低延遲的敏感資產或工作負載維護私有基礎架構。
靈活性——您可以在需要時利用公共雲中的額外資源。
成本效益——通過擴展到公共雲的能力,您只需在需要時為額外的計算能力付費。
輕鬆— 過渡到云不必費力,因為您可以逐步遷移 — 隨著時間的推移逐步分階段遷移工

公共雲

公共雲是最常見的雲計算部署類型。雲資源(如服務器和存儲)由第三方雲服務提供商擁有和運營,並通過互聯網交付。使用公共雲,所有硬件、軟件和其他支持基礎設施都由雲提供商擁有和管理。Microsoft Azure 是公共雲的一個示例。

在公共雲中,您與其他組織或云“租戶”共享相同的硬件、存儲和網絡設備,並使用 Web 瀏覽器訪問服務和管理您的帳戶。公共雲部署經常用於提供基於 Web 的電子郵件、在線辦公應用程序、存儲以及測試和開發環境。

優勢:
降低成本——無需購買硬件或軟件,您只需為使用的服務付費。
無需維護——您的服務提供商提供維護。
近乎無限的可擴展性——按需資源可滿足您的業務需求。
高可靠性——龐大的服務器網絡確保不會出現故障。

私有云由一個企業或組織專門使用的雲計算資源組成。私有云可以物理地位於您組織的現場數據中心,也可以由第三方服務提供商託管。但在私有云中,服務和基礎設施始終在私有網絡上維護,硬件和軟件專門用於您的組織。

通過這種方式,私有云可以讓組織更輕鬆地自定義其資源以滿足特定的 IT 要求。私有云通常被政府機構、金融機構和任何其他具有關鍵業務運營的中大型組織所使用,這些組織尋求增強對環境的控制。

私有雲:

更大的靈活性——您的組織可以自定義其云環境以滿足特定的業務需求。
更多控制——資源不與他人共享,因此可以實現更高級別的控制和隱私。
更高的可擴展性——與本地基礎設施相比,私有云通常提供更高的可擴展性。

解答

答案是 C. 混合式雲端。

推薦資源

Microsoft AZ-900 Exam免費考古題

總結

AZ-900都是以簡單快速記憶為主,不需要深度記憶與推理,廣度大於深度,快速掃過的效益比才是最高的,時間不夠可以直接刷考古題,不建議找太舊的。

可參考當次的考試指南,這樣比較有方向,網路考古題有些答案是錯的,而且分歧極大,遇到這種題目都建議直接找官方文檔。

不過要是像我一樣前天晚上才準備了話建議是直接pass,還記得走出考場的時候只花了一半時間,壓線通過,監考官還疑惑地問說今天怎麼這麼多人都來考,完成後必須在登記表上
簽退,掃了一下當天大概有4個來考,並不是每一位都通過。

https://azure.microsoft.com/en-gb/resources/cloud-computing-dictionary/what-is-iaas/#faq

文章作者: Boris Chien
文章連結: https://www.boris.idv.tw/(%E5%BF%83%E5%BE%97)%E8%80%83%E5%8F%96AZ-900%E5%BF%83%E5%BE%97%E5%88%86%E4%BA%AB/
版權聲明: 本部落格所有文章除特別聲明外,均採用 CC BY-NC-SA 4.0 許可協議。轉載請註明來自 Boris's Blogs

評論
\ No newline at end of file +}
\ No newline at end of file diff --git "a/(\346\212\200\350\241\223)30\347\247\222\350\247\243\346\261\272Dcard\345\275\210\350\267\263\350\246\226\347\252\227/index.html" "b/(\346\212\200\350\241\223)30\347\247\222\350\247\243\346\261\272Dcard\345\275\210\350\267\263\350\246\226\347\252\227/index.html" index 0bb9f07b..b7e81cda 100644 --- "a/(\346\212\200\350\241\223)30\347\247\222\350\247\243\346\261\272Dcard\345\275\210\350\267\263\350\246\226\347\252\227/index.html" +++ "b/(\346\212\200\350\241\223)30\347\247\222\350\247\243\346\261\272Dcard\345\275\210\350\267\263\350\246\226\347\252\227/index.html" @@ -123,7 +123,7 @@ } } detectApple() - })(window)

(技術)30秒解決Dcard彈跳視窗

可以不要一直叫我登入嗎

有時在網路上看到有趣的 Dcard 文章,好奇點進去,看留言時卻跳出討厭的登入視窗,這篇文章會示範如何用開發者工具在 30 秒內關閉

  1. 點擊 F12,開發者工具

  2. 找到彈跳視窗根元素(最外層,屬性 tabindex=”0”),點滑鼠右鍵,刪除元素,這時候就可以看到乾淨漂亮的頁面了~但是還是不能滾動

  3. 往上滑找到 body 元素,element 屬性加上 overflow:scroll

  4. 大功告成,不需要打帳密了

全自動執行

做成 Chrome Extension,這裡提供思路,封裝實作可以參考這篇文章

1
2
3
4
5
6
7
window.addEventListener('load', function() {
const popup = document.getElementById({modal--id});
if (popup) {
popup.remove();
document.body.style.overflow = 'scroll';
}
});

免責聲明

本文僅為客戶端提供教學示範之用,請勿用於任何影響網頁正常運作的技術,否則將自行承擔相應法律責任。

文章作者: Boris Chien
文章連結: https://www.boris.idv.tw/(%E6%8A%80%E8%A1%93)30%E7%A7%92%E8%A7%A3%E6%B1%BADcard%E5%BD%88%E8%B7%B3%E8%A6%96%E7%AA%97/
版權聲明: 本部落格所有文章除特別聲明外,均採用 CC BY-NC-SA 4.0 許可協議。轉載請註明來自 Boris's Blogs

評論
avatar
Boris Chien
網頁前後端開發搭配實作的技術文章與生活紀錄,技術隨筆 https://hackmd.io/@monkeymonkey
Github上找到我
公告
喜歡資訊開發🖥,動手組裝🛠

(技術)30秒解決Dcard彈跳視窗

可以不要一直叫我登入嗎

有時在網路上看到有趣的 Dcard 文章,好奇點進去,看留言時卻跳出討厭的登入視窗,這篇文章會示範如何用開發者工具在 30 秒內關閉

  1. 點擊 F12,開發者工具

  2. 找到彈跳視窗根元素(最外層,屬性 tabindex=“0”),點滑鼠右鍵,刪除元素,這時候就可以看到乾淨漂亮的頁面了~但是還是不能滾動

  3. 往上滑找到 body 元素,element 屬性加上 overflow:scroll

  4. 大功告成,不需要打帳密了

全自動執行

做成 Chrome Extension,這裡提供思路,封裝實作可以參考這篇文章

1
2
3
4
5
6
7
window.addEventListener('load', function() {
const popup = document.getElementById({modal--id});
if (popup) {
popup.remove();
document.body.style.overflow = 'scroll';
}
});

免責聲明

本文僅為客戶端提供教學示範之用,請勿用於任何影響網頁正常運作的技術,否則將自行承擔相應法律責任。

文章作者: Boris Chien
文章連結: https://www.boris.idv.tw/(%E6%8A%80%E8%A1%93)30%E7%A7%92%E8%A7%A3%E6%B1%BADcard%E5%BD%88%E8%B7%B3%E8%A6%96%E7%AA%97/
版權聲明: 本部落格所有文章除特別聲明外,均採用 CC BY-NC-SA 4.0 許可協議。轉載請註明來自 Boris's Blogs

評論
avatar
Boris Chien
網頁前後端開發搭配實作的技術文章與生活紀錄,技術隨筆 https://hackmd.io/@monkeymonkey
Github上找到我
公告
喜歡資訊開發🖥,動手組裝🛠
\ No newline at end of file +}
\ No newline at end of file diff --git "a/(\346\212\200\350\241\223)Laravel-Queue-\350\250\212\346\201\257\351\232\212\345\210\227/index.html" "b/(\346\212\200\350\241\223)Laravel-Queue-\350\250\212\346\201\257\351\232\212\345\210\227/index.html" index bfbe2331..c808d0de 100644 --- "a/(\346\212\200\350\241\223)Laravel-Queue-\350\250\212\346\201\257\351\232\212\345\210\227/index.html" +++ "b/(\346\212\200\350\241\223)Laravel-Queue-\350\250\212\346\201\257\351\232\212\345\210\227/index.html" @@ -1,4 +1,4 @@ -(技術)Laravel-Queue-訊息隊列 | Boris's Blogs

(技術)Laravel-Queue-訊息隊列

Laravel Queue 訊息隊列

特性

  • 異步
  • 重試

常見應用

  • 建立、取消訂單
  • 電子郵件
  • webhook
  • 自動付款、退款
  • 每月報表、帳單
  • 圖片、視頻上傳
  • 更新索引

流程

1.設定config/queue.php.env
2.php artisan queue:table / php artisan migrate
3.php artisan make:job <name>
4.啟動 Queue Listener
5.Supervisor / Horizon 監控

介面

  • 單例 ShouldBeUnique
  • 加密 ShouldBeEncrypted

自選

class 屬性優先於指令

1.重試

1
php artisan queue:work --tries 3

2.優先

1
php artisan queue:work --queue

3.超時

1
php artisan queue:work --timeout

4.middleware

1
2
3
4
public function middleware(): array
{
return [new RateLimited];
}

同步 vs 非同步

同步

訂單支付,同步耗時相當久,無法得到即時響應

order1

order2

1
2
3
4
Route::post('/syncApiTest', function () {
$delaySeconds=5;
sleep($delaySeconds);
});

pending

非同步

1.範例需要,不建議在生產環境中的web.php寫邏輯
2.dispatch 成功,會將任務加入驅動,queue:work時在後台執行

1
2
3
Route::post('/asyncApiTest', function () {
ApiDemo::dispatch();
});

jobs

ref

Laravel 消息队列实战
Queues

文章作者: Boris Chien
文章連結: https://www.boris.idv.tw/(%E6%8A%80%E8%A1%93)Laravel-Queue-%E8%A8%8A%E6%81%AF%E9%9A%8A%E5%88%97/
版權聲明: 本部落格所有文章除特別聲明外,均採用 CC BY-NC-SA 4.0 許可協議。轉載請註明來自 Boris's Blogs

評論

(技術)Laravel-Queue-訊息隊列

Laravel Queue 訊息隊列

特性

  • 異步
  • 重試

常見應用

  • 建立、取消訂單
  • 電子郵件
  • webhook
  • 自動付款、退款
  • 每月報表、帳單
  • 圖片、視頻上傳
  • 更新索引

流程

1.設定config/queue.php.env
2.php artisan queue:table / php artisan migrate
3.php artisan make:job <name>
4.啟動 Queue Listener
5.Supervisor / Horizon 監控

介面

  • 單例 ShouldBeUnique
  • 加密 ShouldBeEncrypted

自選

class 屬性優先於指令

1.重試

1
php artisan queue:work --tries 3

2.優先

1
php artisan queue:work --queue

3.超時

1
php artisan queue:work --timeout

4.middleware

1
2
3
4
public function middleware(): array
{
return [new RateLimited];
}

同步 vs 非同步

同步

訂單支付,同步耗時相當久,無法得到即時響應

order1

order2

1
2
3
4
Route::post('/syncApiTest', function () {
$delaySeconds=5;
sleep($delaySeconds);
});

pending

非同步

1.範例需要,不建議在生產環境中的web.php寫邏輯
2.dispatch 成功,會將任務加入驅動,queue:work時在後台執行

1
2
3
Route::post('/asyncApiTest', function () {
ApiDemo::dispatch();
});

jobs

ref

Laravel 消息队列实战
Queues

文章作者: Boris Chien
文章連結: https://www.boris.idv.tw/(%E6%8A%80%E8%A1%93)Laravel-Queue-%E8%A8%8A%E6%81%AF%E9%9A%8A%E5%88%97/
版權聲明: 本部落格所有文章除特別聲明外,均採用 CC BY-NC-SA 4.0 許可協議。轉載請註明來自 Boris's Blogs

評論
\ No newline at end of file +}
\ No newline at end of file diff --git "a/(\346\212\200\350\241\223)\344\275\277\347\224\250Swagger\347\224\237\346\210\220Laravel\347\232\204API\346\226\207\344\273\266/index.html" "b/(\346\212\200\350\241\223)\344\275\277\347\224\250Swagger\347\224\237\346\210\220Laravel\347\232\204API\346\226\207\344\273\266/index.html" index 04ffdfb7..34c58747 100644 --- "a/(\346\212\200\350\241\223)\344\275\277\347\224\250Swagger\347\224\237\346\210\220Laravel\347\232\204API\346\226\207\344\273\266/index.html" +++ "b/(\346\212\200\350\241\223)\344\275\277\347\224\250Swagger\347\224\237\346\210\220Laravel\347\232\204API\346\226\207\344\273\266/index.html" @@ -1,4 +1,4 @@ -(技術)使用Swagger生成Laravel的API文件 | Boris's Blogs

(技術)使用Swagger生成Laravel的API文件

Swagger 可以用來生成 Laravel API 文件,輕鬆地記錄和分享 API 的資訊,提供了清晰的介面,
讓開發人員更容易了解和使用您的 API。這有助於提高開發效率並確保 API 文檔的一致性

安裝

1
composer require "darkaonline/l5-swagger"

Controller

加入文件版本、標題、描述、授權

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
namespace App\Http\Controllers;

use OpenApi\Annotations as OA;
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
use Illuminate\Foundation\Bus\DispatchesJobs;
use Illuminate\Foundation\Validation\ValidatesRequests;
use Illuminate\Routing\Controller as BaseController;

/**
* @OA\Info(
* version="1.0.0",
* title="Book-RESTful-API",
* description="Login to obtain a JWT, with bearer authorization",
* @OA\Contact(
* email="demo@example.com"
* ),
* @OA\License(
* name="Apache 2.0",
* url="http://www.apache.org/licenses/LICENSE-2.0.html"
* )
* )
*/

class Controller extends BaseController
{
use AuthorizesRequests, DispatchesJobs, ValidatesRequests;
}

BookController

新增CRUD註解

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209

namespace App\Http\Controllers;

use App\Models\Book;
use App\Http\Resources\BookResource;
use Illuminate\Http\Request;

class BookController extends Controller
{
/**
* Display a listing of the resource.
*
* @return \Illuminate\Http\Response
*/

public function __construct()
{
$this->middleware('auth:api')->except(['index', 'show']);
}
/**
* @OA\Get(
* path="/api/books",
* summary="取得最多25筆的書本與評分",
* tags={"Book"},
* @OA\Response(response="200", description="成功",@OA\JsonContent()),
* )
*/
public function index()
{
return BookResource::collection(Book::with('ratings')->paginate(25));
}
/**
* @OA\POST(
* path="/api/books",
* summary="創建書本",
* tags={"Book"},
* @OA\RequestBody(
* required=true,
* @OA\MediaType(
* mediaType="application/json",
* @OA\Schema(
* required={"title", "description"},
* @OA\Property(
* property="title",
* type="string",
* description="標題"
* ),
* @OA\Property(
* property="description",
* type="string",
* description="簡介"
* )
* )
* )
* ),
* @OA\Response(
* response=201,
* description="創建成功"
* ),
* @OA\Response(
* response=401,
* description="未驗證"
* ),
* @OA\Response(
* response=404,
* description="資源不存在"
* ),
* security={{ "bearer_token": {} }}
* )
*/

public function store(Request $request)
{
$book = Book::create([
'user_id' => $request->user()->id,
'title' => $request->title,
'description' => $request->description,
]);

return new BookResource($book);
}

/**
* @OA\Get(
* path="/api/books/{bookId}",
* summary="取得書本",
* tags={"Book"},
* @OA\Parameter(
* name="bookId",
* description="Book id",
* required=true,
* in="path",
* @OA\Schema(
* type="integer"
* )
* ),
* @OA\Response(
* response=200,
* description="成功"
* ),
* @OA\Response(
* response=404,
* description="資源不存在"
* )
* )
*/
public function show(Book $book)
{
return new BookResource($book);
}

/**
* @OA\Patch(
* path="/api/books/{bookId}",
* summary="更新書本",
* tags={"Book"},
* description="更新書本",
* @OA\Parameter(
* name="bookId",
* description="Book id",
* required=true,
* in="path",
* @OA\Schema(
* type="integer"
* )
* ),
* @OA\RequestBody(
* description="更新書本的內容",
* required=true,
* @OA\MediaType(
* mediaType="application/json",
* @OA\Schema(
* type="object",
* @OA\Property(
* property="title",
* description="標題",
* type="string"
* ),
* @OA\Property(
* property="description",
* description="內容",
* type="string"
* ),
* )
* )
* ),
* @OA\Response(
* response=200,
* description="成功",
* @OA\JsonContent()
* ),
* @OA\Response(
* response=401,
* description="未驗證",
* @OA\JsonContent()
* ),
* @OA\Response(
* response=404,
* description="資源不存在",
* @OA\JsonContent()
* ),
* security={{ "bearer_token": {} }}
* )
*/
public function update(Request $request, Book $book)
{
if ($request->user()->id !== $book->user_id) {
return response()->json(['error' => 'You can only edit your own books.'], 403);
}

$book->update($request->only(['title', 'description']));

return new BookResource($book);
}

/**
* @OA\Delete(
* path="/api/books/{bookId}",
* summary="刪除書本",
* tags={"Book"},
* @OA\Parameter(
* name="bookId",
* description="Book id",
* required=true,
* in="path",
* @OA\Schema(
* type="integer"
* )
* ),
* @OA\Response(
* response=204,
* description="刪除成功",
* @OA\JsonContent()
* ),
* @OA\Response(
* response=404,
* description="資源不存在",
* @OA\JsonContent()
* ),
* security={{ "bearer_token": {} }}
* )
*/
public function destroy(Book $book)
{
$book->delete();

return response()->json(null, 204);
}
}

生成文件

1
php artisan l5-swagger:generate

訪問以下路由即可看到文件

1
<server>/api/documention

demo

範例在這

Ref

L5-Swagger
swagger-demo
use JWT Bearer token in swagger Laravel

文章作者: Boris Chien
文章連結: https://www.boris.idv.tw/(%E6%8A%80%E8%A1%93)%E4%BD%BF%E7%94%A8Swagger%E7%94%9F%E6%88%90Laravel%E7%9A%84API%E6%96%87%E4%BB%B6/
版權聲明: 本部落格所有文章除特別聲明外,均採用 CC BY-NC-SA 4.0 許可協議。轉載請註明來自 Boris's Blogs

評論
avatar
Boris Chien
網頁前後端開發搭配實作的技術文章與生活紀錄,技術隨筆 https://hackmd.io/@monkeymonkey
Github上找到我
公告
喜歡資訊開發🖥,動手組裝🛠

(技術)使用Swagger生成Laravel的API文件

Swagger 可以用來生成 Laravel API 文件,輕鬆地記錄和分享 API 的資訊,提供了清晰的介面,
讓開發人員更容易了解和使用您的 API。這有助於提高開發效率並確保 API 文檔的一致性

安裝

1
composer require "darkaonline/l5-swagger"

Controller

加入文件版本、標題、描述、授權

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
namespace App\Http\Controllers;

use OpenApi\Annotations as OA;
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
use Illuminate\Foundation\Bus\DispatchesJobs;
use Illuminate\Foundation\Validation\ValidatesRequests;
use Illuminate\Routing\Controller as BaseController;

/**
* @OA\Info(
* version="1.0.0",
* title="Book-RESTful-API",
* description="Login to obtain a JWT, with bearer authorization",
* @OA\Contact(
* email="demo@example.com"
* ),
* @OA\License(
* name="Apache 2.0",
* url="http://www.apache.org/licenses/LICENSE-2.0.html"
* )
* )
*/

class Controller extends BaseController
{
use AuthorizesRequests, DispatchesJobs, ValidatesRequests;
}

BookController

新增CRUD註解

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209

namespace App\Http\Controllers;

use App\Models\Book;
use App\Http\Resources\BookResource;
use Illuminate\Http\Request;

class BookController extends Controller
{
/**
* Display a listing of the resource.
*
* @return \Illuminate\Http\Response
*/

public function __construct()
{
$this->middleware('auth:api')->except(['index', 'show']);
}
/**
* @OA\Get(
* path="/api/books",
* summary="取得最多25筆的書本與評分",
* tags={"Book"},
* @OA\Response(response="200", description="成功",@OA\JsonContent()),
* )
*/
public function index()
{
return BookResource::collection(Book::with('ratings')->paginate(25));
}
/**
* @OA\POST(
* path="/api/books",
* summary="創建書本",
* tags={"Book"},
* @OA\RequestBody(
* required=true,
* @OA\MediaType(
* mediaType="application/json",
* @OA\Schema(
* required={"title", "description"},
* @OA\Property(
* property="title",
* type="string",
* description="標題"
* ),
* @OA\Property(
* property="description",
* type="string",
* description="簡介"
* )
* )
* )
* ),
* @OA\Response(
* response=201,
* description="創建成功"
* ),
* @OA\Response(
* response=401,
* description="未驗證"
* ),
* @OA\Response(
* response=404,
* description="資源不存在"
* ),
* security={{ "bearer_token": {} }}
* )
*/

public function store(Request $request)
{
$book = Book::create([
'user_id' => $request->user()->id,
'title' => $request->title,
'description' => $request->description,
]);

return new BookResource($book);
}

/**
* @OA\Get(
* path="/api/books/{bookId}",
* summary="取得書本",
* tags={"Book"},
* @OA\Parameter(
* name="bookId",
* description="Book id",
* required=true,
* in="path",
* @OA\Schema(
* type="integer"
* )
* ),
* @OA\Response(
* response=200,
* description="成功"
* ),
* @OA\Response(
* response=404,
* description="資源不存在"
* )
* )
*/
public function show(Book $book)
{
return new BookResource($book);
}

/**
* @OA\Patch(
* path="/api/books/{bookId}",
* summary="更新書本",
* tags={"Book"},
* description="更新書本",
* @OA\Parameter(
* name="bookId",
* description="Book id",
* required=true,
* in="path",
* @OA\Schema(
* type="integer"
* )
* ),
* @OA\RequestBody(
* description="更新書本的內容",
* required=true,
* @OA\MediaType(
* mediaType="application/json",
* @OA\Schema(
* type="object",
* @OA\Property(
* property="title",
* description="標題",
* type="string"
* ),
* @OA\Property(
* property="description",
* description="內容",
* type="string"
* ),
* )
* )
* ),
* @OA\Response(
* response=200,
* description="成功",
* @OA\JsonContent()
* ),
* @OA\Response(
* response=401,
* description="未驗證",
* @OA\JsonContent()
* ),
* @OA\Response(
* response=404,
* description="資源不存在",
* @OA\JsonContent()
* ),
* security={{ "bearer_token": {} }}
* )
*/
public function update(Request $request, Book $book)
{
if ($request->user()->id !== $book->user_id) {
return response()->json(['error' => 'You can only edit your own books.'], 403);
}

$book->update($request->only(['title', 'description']));

return new BookResource($book);
}

/**
* @OA\Delete(
* path="/api/books/{bookId}",
* summary="刪除書本",
* tags={"Book"},
* @OA\Parameter(
* name="bookId",
* description="Book id",
* required=true,
* in="path",
* @OA\Schema(
* type="integer"
* )
* ),
* @OA\Response(
* response=204,
* description="刪除成功",
* @OA\JsonContent()
* ),
* @OA\Response(
* response=404,
* description="資源不存在",
* @OA\JsonContent()
* ),
* security={{ "bearer_token": {} }}
* )
*/
public function destroy(Book $book)
{
$book->delete();

return response()->json(null, 204);
}
}

生成文件

1
php artisan l5-swagger:generate

訪問以下路由即可看到文件

1
<server>/api/documention

demo

範例在這

Ref

L5-Swagger
swagger-demo
use JWT Bearer token in swagger Laravel

文章作者: Boris Chien
文章連結: https://www.boris.idv.tw/(%E6%8A%80%E8%A1%93)%E4%BD%BF%E7%94%A8Swagger%E7%94%9F%E6%88%90Laravel%E7%9A%84API%E6%96%87%E4%BB%B6/
版權聲明: 本部落格所有文章除特別聲明外,均採用 CC BY-NC-SA 4.0 許可協議。轉載請註明來自 Boris's Blogs

評論
avatar
Boris Chien
網頁前後端開發搭配實作的技術文章與生活紀錄,技術隨筆 https://hackmd.io/@monkeymonkey
Github上找到我
公告
喜歡資訊開發🖥,動手組裝🛠
\ No newline at end of file +}
\ No newline at end of file diff --git "a/(\346\212\200\350\241\223)\345\244\247\345\236\213\351\227\234\344\277\202\347\256\241\347\220\206Monica/index.html" "b/(\346\212\200\350\241\223)\345\244\247\345\236\213\351\227\234\344\277\202\347\256\241\347\220\206Monica/index.html" index 0726ed4d..133f66e7 100644 --- "a/(\346\212\200\350\241\223)\345\244\247\345\236\213\351\227\234\344\277\202\347\256\241\347\220\206Monica/index.html" +++ "b/(\346\212\200\350\241\223)\345\244\247\345\236\213\351\227\234\344\277\202\347\256\241\347\220\206Monica/index.html" @@ -1,4 +1,4 @@ -(技術)大型關係管理Monica | Boris's Blogs

(技術)大型關係管理Monica

Monica 是一個開源專案,用於組織和記錄與親人的互動。又稱 PRM,個人關係管理。可將其視為您朋友或家人的 CRM,本文會介紹感興趣的功能,API、數據導出、OAuth、以及 issue。

Monica’s vision is to help people have more meaningful relationships.
幫助人們建立有意義的關係

主打”關係管理”,相較市面成熟的社交產品(如 Facebook),其定位特別,替人脈建立一個管理後台,還記得大學時參加幹訓、社團迎新,認識各社團幹部,常忘記小細節,此產品便能很好地解決這個問題,基於興趣,我也作為翻譯貢獻者,協助 monica 文件繁體中文的在地化,具體參考chienniman/monica
本文會介紹API授權(個人使用、開放授權),數據導出、社群討論issue,也會同時附上以上功能的原始碼分析,深入淺出的介紹設計模式在本專案的應用。

執行&部署

1
2
3
4
PHP 8.1+
HTTP server with PHP support (eg: Apache, Nginx, Caddy)
Composer
MySQL
1
2
Platform.sh
Heroku

官方文件提到,構建專案程式需要 1.5GB RAM 以上,在 GCP 開便宜的 n1-standard-1,每月最少也要 600 台幣

Authentication

在 Monica 中,OAuth 2.0 與個人訪問令牌是兩種不同的身份驗證機制,但它們都用於授權 API 訪問。
OAuth 2.0 是一種標準的開放授權協議,允許用戶在 Monica 上授權第三方應用程序訪問數據,不需要將用戶名和密碼提供給該應用程序。當用戶通過 OAuth 2.0 授權授權應用程序時,該應用程序會收到一個訪問令牌,以便它可以代表用戶訪問 Monica API。
個人訪問令牌則是一種基於 Monica 賬戶的令牌,允許應用程序代表用戶訪問 Monica API。這意味著,當用戶提供他們的個人訪問令牌給應用程序時,該應用程序就可以代表該用戶訪問 API,就像它擁有 OAuth 2.0 訪問令牌一樣。
雖然這兩種令牌都可以用於授權 API 訪問,但它們的使用方式略有不同。 OAuth 2.0 是一種標準的開放授權協議,允許用戶授權第三方應用程序訪問其數據。個人訪問令牌則是一種在 Monica 內部生成的令牌,只能由用戶本人使用。在大多數情況下,建議使用 OAuth 2.0,因為它是更安全和更靈活的身份驗證協議。

個人驗證授權

1
curl -H "Authorization: Bearer Personal access token" https://app.monicahq.com/api

個人驗證令牌(personal-access-token)


將 token 放在 postmon 的 Authorization

postman測試

開放授權(OAuth)

monica 也提供 OAuth 方式驗證 API,向伺服器發起驗證請求,跳出授權允許視窗,取得 Access Token,之後請求夾帶令牌訪問保護資源

流程

Postmon


配置 postmon 參數,將 Callback URL 填入 monica 後台 API,Token name、Client ID、Client Secret 填入 postmon

授權請求


postmon 會跳出授權請求,允許後核發 Access Token、Refresh Token,點擊使用後自動帶入 Authorization Token 欄位

測試請求


The OAuth 2.0 Authorization Framework: Bearer Token Usage
monica-api 文件

第三方登入

官方託管 monica 支持 OAuth API,卻不支持 Facebook、Google 第三方登入,主流的平台為提升用戶體驗,通常會支持,疑惑地查找社群討論發現

degan6 提出 OAuth 登入的 pull request,但被主要開發者拒絕了

1.不想要支持有疑慮的第三方登入(Facebook 疑似洩漏個資事件)
2.官方託管已經移除大多數的追蹤程式碼

數據導出

monica 能輸出聯絡人vCard,使用者Sql、Json 等,相當便利,數據輸出需較長時間處理,隊列任務被存儲在數據庫,在多個請求之間共享任務。當任務被添加到隊列,被插入到表中,等待被執行。Laravel會跟蹤任務的狀態,未處理、處理中、已處理、失敗。
Laravel預設使用同步隊列(sync),保證實時、穩定性,方便進行開發與測試,但對於大量、耗時任務,同步處理會阻塞主線程,因此不適合高併發場景。

vCard


vCard 是電子名片的文件格式標準。它一般附加在電子郵件之後,但也可以用於其它場合(如在網際網路上相互交換)。vCard 可包含的信息有:姓名、地址資訊、電話號碼、URL,logo,相片等。

Routes

1
2
// monica/routes/web.php 
Route::get('/people/{contact}/vcard', 'ContactsController@vcard')->name('vcard');

ContactsController

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// monica/app/Http/Controllers/ContactsController.php
// 依賴注入:Contact、ExportVCard、Str和LocaleHelper通過依賴注入。
public function vCard(Contact $contact)
{
// 禁用 Debugbar 避免在下載 vCard 時,偵錯列(debugbar)出現在輸出中
if (config('app.debug') && class_exists('\Barryvdh\Debugbar\Facade')) {
Debugbar::disable();
}
// Laravel 中的全域輔助函數,用於從應用程式服務容器中取回特定的服務實例
$vcard = app(ExportVCard::class)->execute([
'account_id' => auth()->user()->account_id,
'contact_id' => $contact->id,
]);
// response 函數將 $vcard 序列化後的 VCard 字符串作為內容,設置 'Content-type' 標頭為 'text/x-vcard'
// 表示傳輸的內容是 VCard 格式。同時,設置 'Content-Disposition' 標頭為 'attachment;
// filename='.Str::slug($contact->name, '-', LocaleHelper::getLang()).'.vcf'
// 表示將其作為下載文件附件發送給用戶端,並將文件名設置為聯絡人的名稱轉換為 slug 格式後加上 .vcf 的檔名
return response($vcard->serialize())
->header('Content-type', 'text/x-vcard')
->header('Content-Disposition', 'attachment; filename='.Str::slug($contact->name, '-', LocaleHelper::getLang()).'.vcf');
}

Sql & Json導出

Routes

1
2
3
// monica/routes/web.php 
Route::post('/settings/exportToSql', 'Settings\\ExportController@storeSQL')->name('export.store.sql');
Route::post('/settings/exportToJson', 'Settings\\ExportController@storeJson')->name('export.store.json');

ExportJob

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
// monica/app/Models/Account/ExportJob.php 
namespace App\Models\Account;

use App\Traits\HasUuid;
use App\Models\User\User;
use Illuminate\Database\Eloquent\Model;
use App\Notifications\ExportAccountDone;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Factories\HasFactory;

class ExportJob extends Model
{
use HasUuid, HasFactory;

public const EXPORT_TODO = 'todo';
public const EXPORT_DOING = 'doing';
public const EXPORT_DONE = 'done';
public const EXPORT_FAILED = 'failed';

public const SQL = 'sql';

public const JSON = 'json';

protected $fillable = [
'uuid',
'account_id',
'user_id',
'type',
'status',
'filesystem',
'filename',
'started_at',
'ended_at',
];

protected $guarded = ['id'];

protected $dates = [
'started_at',
'ended_at',
];

public function account()
{
return $this->belongsTo(Account::class);
}

public function user()
{
return $this->belongsTo(User::class);
}

public function start(): void
{
$this->status = self::EXPORT_DOING;
$this->started_at = now();
$this->save();
}

// 發信通知
public function end(): void
{
$this->status = self::EXPORT_DONE;
$this->ended_at = now();
$this->save();

$this->user->notify(new ExportAccountDone($this));
}
}

ExportController

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
// monica/app/Http/Controllers/Settings/ExportController.php
private function newExport(string $type): ExportJob
{
$exports = ExportJob::where([
'account_id' => auth()->user()->account_id,
'user_id' => auth()->user()->id,
])
->orderBy('created_at')
->get();
// 輸出任務總量超過最大配置,刪除最舊的任務
if ($exports->count() >= config('monica.export_size')) {
$job = $exports->first();
try {
if ($job->filename !== null) {
StorageHelper::disk($job->location)
->delete($job->filename);
}
} finally {
// 確保釋放資源,避免內存洩漏、資源浪費
$job->delete();
}
}
// 回傳剛建立的實例資料
return ExportJob::create([
'account_id' => auth()->user()->account_id,
'user_id' => auth()->user()->id,
'type' => $type,
]);
}

public function storeSql()
{
$job = $this->newExport(ExportJob::SQL);
ExportAccount::dispatch($job);

return redirect()->route('settings.export.index')
->withStatus(trans('settings.export_submitted'));
}

public function storeJson()
{
$job = $this->newExport(ExportJob::JSON);
ExportAccount::dispatch($job);

return redirect()->route('settings.export.index')
->withStatus(trans('settings.export_submitted'));

}

Dispatch

1
2
3
4
5
// framework/src/Illuminate/Foundation/Bus/Dispatchable.php 
public static function dispatch(...$arguments)
{
return new PendingDispatch(new static(...$arguments));
}

PendingDispatch

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
// framework/src/Illuminate/Foundation/Bus/PendingDispatch.php 
// 提供了一個額外的介面,讓使用者可以更方便地調用 Job 物件的方法。同時,在物件的銷毀時刻,
// PendingDispatch 會根據 $this->afterResponse 屬性來決定要如何分派 $this->job。
namespace Illuminate\Foundation\Bus;

use Illuminate\Bus\UniqueLock;
use Illuminate\Container\Container;
use Illuminate\Contracts\Bus\Dispatcher;
use Illuminate\Contracts\Cache\Repository as Cache;
use Illuminate\Contracts\Queue\ShouldBeUnique;

class PendingDispatch
{
protected $job;

protected $afterResponse = false;

public function __construct($job)
{
$this->job = $job;
}

public function onConnection($connection)
{
$this->job->onConnection($connection);

return $this;
}

public function onQueue($queue)
{
$this->job->onQueue($queue);

return $this;
}

public function allOnConnection($connection)
{
$this->job->allOnConnection($connection);

return $this;
}

public function allOnQueue($queue)
{
$this->job->allOnQueue($queue);

return $this;
}

public function delay($delay)
{
$this->job->delay($delay);

return $this;
}

public function afterCommit()
{
$this->job->afterCommit();

return $this;
}

public function beforeCommit()
{
$this->job->beforeCommit();

return $this;
}

public function chain($chain)
{
$this->job->chain($chain);

return $this;
}

public function afterResponse()
{
$this->afterResponse = true;

return $this;
}

// 實現對任務調度執行的控制,確保同一個唯一的任務在同一時間只會被調度執行一次。
// 返回true,則表示當前任務可以被調度執行,否則返回false,表示該任務已經被另一個進程或線程佔用了
protected function shouldDispatch()
{
if (! $this->job instanceof ShouldBeUnique) {
return true;
}

return (new UniqueLock(Container::getInstance()->make(Cache::class)))
->acquire($this->job);
}

// $pendingDispatch 可以透過 __call 方法動態調用 $job 實例上的任何方法
public function __call($method, $parameters)
{
$this->job->{$method}(...$parameters);

return $this;
}
// 任務調度的判斷
public function __destruct()
{
if (! $this->shouldDispatch()) {
return;
} elseif ($this->afterResponse) {
app(Dispatcher::class)->dispatchAfterResponse($this->job);
} else {
app(Dispatcher::class)->dispatch($this->job);
}
}
}

成功通知

發信notify

1
2
3
4
5
6
7
8
9
// monica/app/Models/Account/ExportJob.php 
public function end(): void
{
$this->status = self::EXPORT_DONE;
$this->ended_at = now();
$this->save();

$this->user->notify(new ExportAccountDone($this));
}

ExportAccountDone

1
2
3
4
5
6
7
8
9
10
11
12
13
// monica/app/Notifications/ExportAccountDone.php 
public function toMail(User $user): MailMessage
{
$date = Carbon::parse($this->exportJob->created_at)
->setTimezone($user->timezone);
// 成功、主題、歡迎詞、描述、下載連結
return (new MailMessage)
->success()
->subject(trans('mail.export_title'))
->greeting(trans('mail.greetings', ['username' => $user->first_name]))
->line(trans('mail.export_description', ['date' => DateHelper::getShortDate($date)]))
->action(trans('mail.export_download'), route('settings.export.index'));
}

下載資源

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// monica/app/Http/Controllers/Settings/ExportController.php 
public function download(Request $request, string $uuid)
{
// 查詢第一筆紀錄
$job = ExportJob::where([
'account_id' => auth()->user()->account_id,
'user_id' => auth()->user()->id,
'uuid' => $uuid,
])->firstOrFail();

// 未完成
if ($job->status !== ExportJob::EXPORT_DONE) {
return redirect()->route('settings.export.index')
->withErrors(trans('settings.export_not_done'));
}
$disk = StorageHelper::disk($job->location);

// 返回請求資料
return $disk->response($job->filename,
"monica.{$job->type}",
[
'Content-Type' => "application/{$job->type}; charset=utf-8",
'Content-Disposition' => "attachment; filename=monica.{$job->type}",
]
);
}
文章作者: Boris Chien
文章連結: https://www.boris.idv.tw/(%E6%8A%80%E8%A1%93)%E5%A4%A7%E5%9E%8B%E9%97%9C%E4%BF%82%E7%AE%A1%E7%90%86Monica/
版權聲明: 本部落格所有文章除特別聲明外,均採用 CC BY-NC-SA 4.0 許可協議。轉載請註明來自 Boris's Blogs

評論

(技術)大型關係管理Monica

Monica 是一個開源專案,用於組織和記錄與親人的互動。又稱 PRM,個人關係管理。可將其視為您朋友或家人的 CRM,本文會介紹感興趣的功能,API、數據導出、OAuth、以及 issue。

Monica’s vision is to help people have more meaningful relationships.
幫助人們建立有意義的關係

主打"關係管理",相較市面成熟的社交產品(如 Facebook),其定位特別,替人脈建立一個管理後台,還記得大學時參加幹訓、社團迎新,認識各社團幹部,常忘記小細節,此產品便能很好地解決這個問題,基於興趣,我也作為翻譯貢獻者,協助 monica 文件繁體中文的在地化,具體參考chienniman/monica
本文會介紹API授權(個人使用、開放授權),數據導出、社群討論issue,也會同時附上以上功能的原始碼分析,深入淺出的介紹設計模式在本專案的應用。

執行&部署

1
2
3
4
PHP 8.1+
HTTP server with PHP support (eg: Apache, Nginx, Caddy)
Composer
MySQL
1
2
Platform.sh
Heroku

官方文件提到,構建專案程式需要 1.5GB RAM 以上,在 GCP 開便宜的 n1-standard-1,每月最少也要 600 台幣

Authentication

在 Monica 中,OAuth 2.0 與個人訪問令牌是兩種不同的身份驗證機制,但它們都用於授權 API 訪問。
OAuth 2.0 是一種標準的開放授權協議,允許用戶在 Monica 上授權第三方應用程序訪問數據,不需要將用戶名和密碼提供給該應用程序。當用戶通過 OAuth 2.0 授權授權應用程序時,該應用程序會收到一個訪問令牌,以便它可以代表用戶訪問 Monica API。
個人訪問令牌則是一種基於 Monica 賬戶的令牌,允許應用程序代表用戶訪問 Monica API。這意味著,當用戶提供他們的個人訪問令牌給應用程序時,該應用程序就可以代表該用戶訪問 API,就像它擁有 OAuth 2.0 訪問令牌一樣。
雖然這兩種令牌都可以用於授權 API 訪問,但它們的使用方式略有不同。 OAuth 2.0 是一種標準的開放授權協議,允許用戶授權第三方應用程序訪問其數據。個人訪問令牌則是一種在 Monica 內部生成的令牌,只能由用戶本人使用。在大多數情況下,建議使用 OAuth 2.0,因為它是更安全和更靈活的身份驗證協議。

個人驗證授權

1
curl -H "Authorization: Bearer Personal access token" https://app.monicahq.com/api

個人驗證令牌(personal-access-token)


將 token 放在 postmon 的 Authorization

postman測試

開放授權(OAuth)

monica 也提供 OAuth 方式驗證 API,向伺服器發起驗證請求,跳出授權允許視窗,取得 Access Token,之後請求夾帶令牌訪問保護資源

流程

Postmon


配置 postmon 參數,將 Callback URL 填入 monica 後台 API,Token name、Client ID、Client Secret 填入 postmon

授權請求


postmon 會跳出授權請求,允許後核發 Access Token、Refresh Token,點擊使用後自動帶入 Authorization Token 欄位

測試請求


The OAuth 2.0 Authorization Framework: Bearer Token Usage
monica-api 文件

第三方登入

官方託管 monica 支持 OAuth API,卻不支持 Facebook、Google 第三方登入,主流的平台為提升用戶體驗,通常會支持,疑惑地查找社群討論發現

degan6 提出 OAuth 登入的 pull request,但被主要開發者拒絕了

1.不想要支持有疑慮的第三方登入(Facebook 疑似洩漏個資事件)
2.官方託管已經移除大多數的追蹤程式碼

數據導出

monica 能輸出聯絡人vCard,使用者Sql、Json 等,相當便利,數據輸出需較長時間處理,隊列任務被存儲在數據庫,在多個請求之間共享任務。當任務被添加到隊列,被插入到表中,等待被執行。Laravel會跟蹤任務的狀態,未處理、處理中、已處理、失敗。
Laravel預設使用同步隊列(sync),保證實時、穩定性,方便進行開發與測試,但對於大量、耗時任務,同步處理會阻塞主線程,因此不適合高併發場景。

vCard


vCard 是電子名片的文件格式標準。它一般附加在電子郵件之後,但也可以用於其它場合(如在網際網路上相互交換)。vCard 可包含的信息有:姓名、地址資訊、電話號碼、URL,logo,相片等。

Routes

1
2
// monica/routes/web.php 
Route::get('/people/{contact}/vcard', 'ContactsController@vcard')->name('vcard');

ContactsController

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// monica/app/Http/Controllers/ContactsController.php
// 依賴注入:Contact、ExportVCard、Str和LocaleHelper通過依賴注入。
public function vCard(Contact $contact)
{
// 禁用 Debugbar 避免在下載 vCard 時,偵錯列(debugbar)出現在輸出中
if (config('app.debug') && class_exists('\Barryvdh\Debugbar\Facade')) {
Debugbar::disable();
}
// Laravel 中的全域輔助函數,用於從應用程式服務容器中取回特定的服務實例
$vcard = app(ExportVCard::class)->execute([
'account_id' => auth()->user()->account_id,
'contact_id' => $contact->id,
]);
// response 函數將 $vcard 序列化後的 VCard 字符串作為內容,設置 'Content-type' 標頭為 'text/x-vcard'
// 表示傳輸的內容是 VCard 格式。同時,設置 'Content-Disposition' 標頭為 'attachment;
// filename='.Str::slug($contact->name, '-', LocaleHelper::getLang()).'.vcf'
// 表示將其作為下載文件附件發送給用戶端,並將文件名設置為聯絡人的名稱轉換為 slug 格式後加上 .vcf 的檔名
return response($vcard->serialize())
->header('Content-type', 'text/x-vcard')
->header('Content-Disposition', 'attachment; filename='.Str::slug($contact->name, '-', LocaleHelper::getLang()).'.vcf');
}

Sql & Json導出

Routes

1
2
3
// monica/routes/web.php 
Route::post('/settings/exportToSql', 'Settings\\ExportController@storeSQL')->name('export.store.sql');
Route::post('/settings/exportToJson', 'Settings\\ExportController@storeJson')->name('export.store.json');

ExportJob

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
// monica/app/Models/Account/ExportJob.php 
namespace App\Models\Account;

use App\Traits\HasUuid;
use App\Models\User\User;
use Illuminate\Database\Eloquent\Model;
use App\Notifications\ExportAccountDone;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Factories\HasFactory;

class ExportJob extends Model
{
use HasUuid, HasFactory;

public const EXPORT_TODO = 'todo';
public const EXPORT_DOING = 'doing';
public const EXPORT_DONE = 'done';
public const EXPORT_FAILED = 'failed';

public const SQL = 'sql';

public const JSON = 'json';

protected $fillable = [
'uuid',
'account_id',
'user_id',
'type',
'status',
'filesystem',
'filename',
'started_at',
'ended_at',
];

protected $guarded = ['id'];

protected $dates = [
'started_at',
'ended_at',
];

public function account()
{
return $this->belongsTo(Account::class);
}

public function user()
{
return $this->belongsTo(User::class);
}

public function start(): void
{
$this->status = self::EXPORT_DOING;
$this->started_at = now();
$this->save();
}

// 發信通知
public function end(): void
{
$this->status = self::EXPORT_DONE;
$this->ended_at = now();
$this->save();

$this->user->notify(new ExportAccountDone($this));
}
}

ExportController

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
// monica/app/Http/Controllers/Settings/ExportController.php
private function newExport(string $type): ExportJob
{
$exports = ExportJob::where([
'account_id' => auth()->user()->account_id,
'user_id' => auth()->user()->id,
])
->orderBy('created_at')
->get();
// 輸出任務總量超過最大配置,刪除最舊的任務
if ($exports->count() >= config('monica.export_size')) {
$job = $exports->first();
try {
if ($job->filename !== null) {
StorageHelper::disk($job->location)
->delete($job->filename);
}
} finally {
// 確保釋放資源,避免內存洩漏、資源浪費
$job->delete();
}
}
// 回傳剛建立的實例資料
return ExportJob::create([
'account_id' => auth()->user()->account_id,
'user_id' => auth()->user()->id,
'type' => $type,
]);
}

public function storeSql()
{
$job = $this->newExport(ExportJob::SQL);
ExportAccount::dispatch($job);

return redirect()->route('settings.export.index')
->withStatus(trans('settings.export_submitted'));
}

public function storeJson()
{
$job = $this->newExport(ExportJob::JSON);
ExportAccount::dispatch($job);

return redirect()->route('settings.export.index')
->withStatus(trans('settings.export_submitted'));

}

Dispatch

1
2
3
4
5
// framework/src/Illuminate/Foundation/Bus/Dispatchable.php 
public static function dispatch(...$arguments)
{
return new PendingDispatch(new static(...$arguments));
}

PendingDispatch

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
// framework/src/Illuminate/Foundation/Bus/PendingDispatch.php 
// 提供了一個額外的介面,讓使用者可以更方便地調用 Job 物件的方法。同時,在物件的銷毀時刻,
// PendingDispatch 會根據 $this->afterResponse 屬性來決定要如何分派 $this->job。
namespace Illuminate\Foundation\Bus;

use Illuminate\Bus\UniqueLock;
use Illuminate\Container\Container;
use Illuminate\Contracts\Bus\Dispatcher;
use Illuminate\Contracts\Cache\Repository as Cache;
use Illuminate\Contracts\Queue\ShouldBeUnique;

class PendingDispatch
{
protected $job;

protected $afterResponse = false;

public function __construct($job)
{
$this->job = $job;
}

public function onConnection($connection)
{
$this->job->onConnection($connection);

return $this;
}

public function onQueue($queue)
{
$this->job->onQueue($queue);

return $this;
}

public function allOnConnection($connection)
{
$this->job->allOnConnection($connection);

return $this;
}

public function allOnQueue($queue)
{
$this->job->allOnQueue($queue);

return $this;
}

public function delay($delay)
{
$this->job->delay($delay);

return $this;
}

public function afterCommit()
{
$this->job->afterCommit();

return $this;
}

public function beforeCommit()
{
$this->job->beforeCommit();

return $this;
}

public function chain($chain)
{
$this->job->chain($chain);

return $this;
}

public function afterResponse()
{
$this->afterResponse = true;

return $this;
}

// 實現對任務調度執行的控制,確保同一個唯一的任務在同一時間只會被調度執行一次。
// 返回true,則表示當前任務可以被調度執行,否則返回false,表示該任務已經被另一個進程或線程佔用了
protected function shouldDispatch()
{
if (! $this->job instanceof ShouldBeUnique) {
return true;
}

return (new UniqueLock(Container::getInstance()->make(Cache::class)))
->acquire($this->job);
}

// $pendingDispatch 可以透過 __call 方法動態調用 $job 實例上的任何方法
public function __call($method, $parameters)
{
$this->job->{$method}(...$parameters);

return $this;
}
// 任務調度的判斷
public function __destruct()
{
if (! $this->shouldDispatch()) {
return;
} elseif ($this->afterResponse) {
app(Dispatcher::class)->dispatchAfterResponse($this->job);
} else {
app(Dispatcher::class)->dispatch($this->job);
}
}
}

成功通知

發信notify

1
2
3
4
5
6
7
8
9
// monica/app/Models/Account/ExportJob.php 
public function end(): void
{
$this->status = self::EXPORT_DONE;
$this->ended_at = now();
$this->save();

$this->user->notify(new ExportAccountDone($this));
}

ExportAccountDone

1
2
3
4
5
6
7
8
9
10
11
12
13
// monica/app/Notifications/ExportAccountDone.php 
public function toMail(User $user): MailMessage
{
$date = Carbon::parse($this->exportJob->created_at)
->setTimezone($user->timezone);
// 成功、主題、歡迎詞、描述、下載連結
return (new MailMessage)
->success()
->subject(trans('mail.export_title'))
->greeting(trans('mail.greetings', ['username' => $user->first_name]))
->line(trans('mail.export_description', ['date' => DateHelper::getShortDate($date)]))
->action(trans('mail.export_download'), route('settings.export.index'));
}

下載資源

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// monica/app/Http/Controllers/Settings/ExportController.php 
public function download(Request $request, string $uuid)
{
// 查詢第一筆紀錄
$job = ExportJob::where([
'account_id' => auth()->user()->account_id,
'user_id' => auth()->user()->id,
'uuid' => $uuid,
])->firstOrFail();

// 未完成
if ($job->status !== ExportJob::EXPORT_DONE) {
return redirect()->route('settings.export.index')
->withErrors(trans('settings.export_not_done'));
}
$disk = StorageHelper::disk($job->location);

// 返回請求資料
return $disk->response($job->filename,
"monica.{$job->type}",
[
'Content-Type' => "application/{$job->type}; charset=utf-8",
'Content-Disposition' => "attachment; filename=monica.{$job->type}",
]
);
}
文章作者: Boris Chien
文章連結: https://www.boris.idv.tw/(%E6%8A%80%E8%A1%93)%E5%A4%A7%E5%9E%8B%E9%97%9C%E4%BF%82%E7%AE%A1%E7%90%86Monica/
版權聲明: 本部落格所有文章除特別聲明外,均採用 CC BY-NC-SA 4.0 許可協議。轉載請註明來自 Boris's Blogs

評論
\ No newline at end of file +}
\ No newline at end of file diff --git "a/(\346\212\200\350\241\223)\345\257\246\344\275\234Laravel-RESTful-API\350\210\207JWT\351\251\227\350\255\211/index.html" "b/(\346\212\200\350\241\223)\345\257\246\344\275\234Laravel-RESTful-API\350\210\207JWT\351\251\227\350\255\211/index.html" index dab5971e..e9afebed 100644 --- "a/(\346\212\200\350\241\223)\345\257\246\344\275\234Laravel-RESTful-API\350\210\207JWT\351\251\227\350\255\211/index.html" +++ "b/(\346\212\200\350\241\223)\345\257\246\344\275\234Laravel-RESTful-API\350\210\207JWT\351\251\227\350\255\211/index.html" @@ -1,4 +1,4 @@ -(技術)實作Laravel-RESTful-API與JWT驗證 | Boris's Blogs

(技術)實作Laravel-RESTful-API與JWT驗證

RESTful API

Representational State Transfer (REST) 是一種軟體架構,它對 API 的運作方式施加了條件。REST 最初是作為管理複雜網路 (如網際網路) 上的通訊指導方針而建立。您可以使用以 REST 為基礎的架構,來支援大規模的高效能和可靠的通訊。您可以輕鬆實作和修改,為任何 API 系統提供可視性和跨平台可移植性。

風格

  • 統一介面
  • 無狀態
  • 分層系統
  • 可快取性
  • 隨需編碼

方法

  • URL
  • GET
  • POST
  • PUT
  • DELETE

幂等

同樣的請求被執行一次與連續執行多次,在伺服器的效果是一樣的,GET、HEAD、PUT、DELETE 是冪等的,POST 方法不是

JWT

JSON Web Token,在伺服器間將訊息作為 JSON 物件傳輸,由 header、payload、signature 組成,
常搭配 RESTful API 作為身分驗證。

實作

安裝

1
composer require tymon/jwt-auth

生成密鑰

1
php artisan jwt:secret

創建 BookResource、BookController

1
php artisan make:resource BookResource
1
php artisan make:controller BookController --api

加入 Middleware

1
2
3
4
public function __construct()
{
$this->middleware('auth:api')->except(['index', 'show']);
}

Postmon 測試

登入取得 access token,預設有效時間一小時

加入 API Header,用來驗證使用者身分

1
Authorization : Bearer <access token>

成功新增資源

demo

範例在這

Ref

什麼是 RESTful API?
冪等
Build a REST API with Laravel API resources

文章作者: Boris Chien
文章連結: https://www.boris.idv.tw/(%E6%8A%80%E8%A1%93)%E5%AF%A6%E4%BD%9CLaravel-RESTful-API%E8%88%87JWT%E9%A9%97%E8%AD%89/
版權聲明: 本部落格所有文章除特別聲明外,均採用 CC BY-NC-SA 4.0 許可協議。轉載請註明來自 Boris's Blogs

評論

(技術)實作Laravel-RESTful-API與JWT驗證

RESTful API

Representational State Transfer (REST) 是一種軟體架構,它對 API 的運作方式施加了條件。REST 最初是作為管理複雜網路 (如網際網路) 上的通訊指導方針而建立。您可以使用以 REST 為基礎的架構,來支援大規模的高效能和可靠的通訊。您可以輕鬆實作和修改,為任何 API 系統提供可視性和跨平台可移植性。

風格

  • 統一介面
  • 無狀態
  • 分層系統
  • 可快取性
  • 隨需編碼

方法

  • URL
  • GET
  • POST
  • PUT
  • DELETE

幂等

同樣的請求被執行一次與連續執行多次,在伺服器的效果是一樣的,GET、HEAD、PUT、DELETE 是冪等的,POST 方法不是

JWT

JSON Web Token,在伺服器間將訊息作為 JSON 物件傳輸,由 header、payload、signature 組成,
常搭配 RESTful API 作為身分驗證。

實作

安裝

1
composer require tymon/jwt-auth

生成密鑰

1
php artisan jwt:secret

創建 BookResource、BookController

1
php artisan make:resource BookResource
1
php artisan make:controller BookController --api

加入 Middleware

1
2
3
4
public function __construct()
{
$this->middleware('auth:api')->except(['index', 'show']);
}

Postmon 測試

登入取得 access token,預設有效時間一小時

加入 API Header,用來驗證使用者身分

1
Authorization : Bearer <access token>

成功新增資源

demo

範例在這

Ref

什麼是 RESTful API?
冪等
Build a REST API with Laravel API resources

文章作者: Boris Chien
文章連結: https://www.boris.idv.tw/(%E6%8A%80%E8%A1%93)%E5%AF%A6%E4%BD%9CLaravel-RESTful-API%E8%88%87JWT%E9%A9%97%E8%AD%89/
版權聲明: 本部落格所有文章除特別聲明外,均採用 CC BY-NC-SA 4.0 許可協議。轉載請註明來自 Boris's Blogs

評論
\ No newline at end of file +}
\ No newline at end of file diff --git "a/(\346\212\200\350\241\223)\346\267\272\350\253\207\344\274\272\346\234\215\345\231\250\347\232\204\346\216\210\346\254\212\343\200\201\351\251\227\350\255\211/index.html" "b/(\346\212\200\350\241\223)\346\267\272\350\253\207\344\274\272\346\234\215\345\231\250\347\232\204\346\216\210\346\254\212\343\200\201\351\251\227\350\255\211/index.html" index 4539253c..de36b307 100644 --- "a/(\346\212\200\350\241\223)\346\267\272\350\253\207\344\274\272\346\234\215\345\231\250\347\232\204\346\216\210\346\254\212\343\200\201\351\251\227\350\255\211/index.html" +++ "b/(\346\212\200\350\241\223)\346\267\272\350\253\207\344\274\272\346\234\215\345\231\250\347\232\204\346\216\210\346\254\212\343\200\201\351\251\227\350\255\211/index.html" @@ -1,4 +1,4 @@ -(技術)淺談伺服器的授權、驗證 | Boris's Blogs

(技術)淺談伺服器的授權、驗證

Authentication

驗證,告訴伺服器登入者是其所聲稱的使用者,以遊戲登入舉例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
+------------------------+        
| 遊戲客戶端啟動 |
+-----------+------------+
|
| 向遊戲伺服器發送認證請求
|
+-----------v------------+
| 遊戲伺服器進行認證 |
+-----------+------------+
|
| 驗證玩家帳號和密碼是否正確、權限(有無鎖帳號)
|
+-----------v------------+
| 確認帳號和密碼正確 |
+-----------+------------+
|
| 允許進入遊戲伺服器
|
+-----------v------------+
| 排隊進入遊戲 |
+------------------------+

Authorization

當玩家通過驗證進入遊戲伺服器後,伺服器會根據玩家的帳戶資料進行授權,假設想要2023的年槍,紫炫流光,就得向伺服器獲得授權,買解碼器、黑市,才能解鎖新武器。

簡單舉例

1
2
購買武器 -> 檢查是否有足夠點數 -> 扣款授權 -> 武器授權 -> 成功購買 

每個玩家客戶端都有全部種類的武器,來自於每次的更新檔,是為了提升遊戲體驗,總不能撿到新槍再下載吧,因此授權只是向伺服器請求,解鎖不能使用的武器。

Https Authentication(Basic)

一種HTTP驗證機制,Base64將用戶名和密碼進行編碼,然後在HTTP請求中以Authorization標頭的形式傳送。簡單來說,當使用者輸入用戶名和密碼時,這些數據將被編碼並包含在HTTP請求中,伺服器收到請求後會解碼這些數據並進行身份驗證。

jigsaw demo

jigsaw.w3.org測試網址

1
2
ac:guest
pw:guest
  • 伺服器檢查在Header裡的Authorization欄位,規格應為 Authorization: Basic <value>
  • 此時因為沒有Authorization並沒有資料,server按照約定會回傳401 status code並在Header上加上 WWW-Authenticate: Basic realm="<value>"
  • client當發現得到以上的回應後,會出現一個給予使用者輸入用戶名稱及密碼的地方
  • client將用戶名稱跟密碼做成base64(username:password)
  • client將資料放到Header: Authorization: base64(username:password)

先生你誰?-身分驗證Authentication (Basic, token, JWT)

把header的authentication取出base64解碼可以看到正好是輸入的帳密

1
base64(username:password)

Digest:

摘要訪問認證是一種協議規定的Web伺服器用來同網頁瀏覽器進行認證信息協商的方法。它在密碼發出前,先對其應用哈希函數,相對於HTTP基本認證發送明文而言,更安全。
https://zh.wikipedia.org/zh-tw/HTTP%E6%91%98%E8%A6%81%E8%AE%A4%E8%AF%81

  • 客戶端向服務器發送請求。
  • 服務器回復401和WWW-Authenticate,nonce(服務器生成的隨機字符串,防止重放攻擊)。
    1
    2
    3
    4
    www-authenticate: 
    Digest realm="test",
    domain="/HTTP/Digest",
    nonce="e67010901fb034b2e0e0c9e0c1f451d8"
  • 客戶端使用用戶名、領域和密碼計算出HA1值,使用請求方式和請求URI計算出HA2值。
  • 客戶端使用HA1、nonce和HA2計算出響應值,加到“Authorization”的header。
    1
    2
    3
    HA1 = MD5(username:realm:password)
    HA2 = MD5(method:digestURI)
    response = MD5(HA1:nonce:HA2)
  • 服務器使用相同的計算方式驗證。如果正確,服務器會返回請求的資源,否則,返回401未授權或其他錯誤狀態碼,客戶端必須重新進行身份驗證。
文章作者: Boris Chien
文章連結: https://www.boris.idv.tw/(%E6%8A%80%E8%A1%93)%E6%B7%BA%E8%AB%87%E4%BC%BA%E6%9C%8D%E5%99%A8%E7%9A%84%E6%8E%88%E6%AC%8A%E3%80%81%E9%A9%97%E8%AD%89/
版權聲明: 本部落格所有文章除特別聲明外,均採用 CC BY-NC-SA 4.0 許可協議。轉載請註明來自 Boris's Blogs

評論
avatar
Boris Chien
網頁前後端開發搭配實作的技術文章與生活紀錄,技術隨筆 https://hackmd.io/@monkeymonkey
Github上找到我
公告
喜歡資訊開發🖥,動手組裝🛠

(技術)淺談伺服器的授權、驗證

Authentication

驗證,告訴伺服器登入者是其所聲稱的使用者,以遊戲登入舉例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
+------------------------+        
| 遊戲客戶端啟動 |
+-----------+------------+
|
| 向遊戲伺服器發送認證請求
|
+-----------v------------+
| 遊戲伺服器進行認證 |
+-----------+------------+
|
| 驗證玩家帳號和密碼是否正確、權限(有無鎖帳號)
|
+-----------v------------+
| 確認帳號和密碼正確 |
+-----------+------------+
|
| 允許進入遊戲伺服器
|
+-----------v------------+
| 排隊進入遊戲 |
+------------------------+

Authorization

當玩家通過驗證進入遊戲伺服器後,伺服器會根據玩家的帳戶資料進行授權,假設想要2023的年槍,紫炫流光,就得向伺服器獲得授權,買解碼器、黑市,才能解鎖新武器。

簡單舉例

1
2
購買武器 -> 檢查是否有足夠點數 -> 扣款授權 -> 武器授權 -> 成功購買 

每個玩家客戶端都有全部種類的武器,來自於每次的更新檔,是為了提升遊戲體驗,總不能撿到新槍再下載吧,因此授權只是向伺服器請求,解鎖不能使用的武器。

Https Authentication(Basic)

一種HTTP驗證機制,Base64將用戶名和密碼進行編碼,然後在HTTP請求中以Authorization標頭的形式傳送。簡單來說,當使用者輸入用戶名和密碼時,這些數據將被編碼並包含在HTTP請求中,伺服器收到請求後會解碼這些數據並進行身份驗證。

jigsaw demo

jigsaw.w3.org測試網址

1
2
ac:guest
pw:guest
  • 伺服器檢查在Header裡的Authorization欄位,規格應為 Authorization: Basic <value>
  • 此時因為沒有Authorization並沒有資料,server按照約定會回傳401 status code並在Header上加上 WWW-Authenticate: Basic realm="<value>"
  • client當發現得到以上的回應後,會出現一個給予使用者輸入用戶名稱及密碼的地方
  • client將用戶名稱跟密碼做成base64(username:password)
  • client將資料放到Header: Authorization: base64(username:password)

先生你誰?-身分驗證Authentication (Basic, token, JWT)

把header的authentication取出base64解碼可以看到正好是輸入的帳密

1
base64(username:password)

Digest:

摘要訪問認證是一種協議規定的Web伺服器用來同網頁瀏覽器進行認證信息協商的方法。它在密碼發出前,先對其應用哈希函數,相對於HTTP基本認證發送明文而言,更安全。
https://zh.wikipedia.org/zh-tw/HTTP%E6%91%98%E8%A6%81%E8%AE%A4%E8%AF%81

  • 客戶端向服務器發送請求。
  • 服務器回復401和WWW-Authenticate,nonce(服務器生成的隨機字符串,防止重放攻擊)。
1
2
3
4
www-authenticate: 
Digest realm="test",
domain="/HTTP/Digest",
nonce="e67010901fb034b2e0e0c9e0c1f451d8"
  • 客戶端使用用戶名、領域和密碼計算出HA1值,使用請求方式和請求URI計算出HA2值。
  • 客戶端使用HA1、nonce和HA2計算出響應值,加到“Authorization”的header。
1
2
3
HA1 = MD5(username:realm:password)
HA2 = MD5(method:digestURI)
response = MD5(HA1:nonce:HA2)
  • 服務器使用相同的計算方式驗證。如果正確,服務器會返回請求的資源,否則,返回401未授權或其他錯誤狀態碼,客戶端必須重新進行身份驗證。
文章作者: Boris Chien
文章連結: https://www.boris.idv.tw/(%E6%8A%80%E8%A1%93)%E6%B7%BA%E8%AB%87%E4%BC%BA%E6%9C%8D%E5%99%A8%E7%9A%84%E6%8E%88%E6%AC%8A%E3%80%81%E9%A9%97%E8%AD%89/
版權聲明: 本部落格所有文章除特別聲明外,均採用 CC BY-NC-SA 4.0 許可協議。轉載請註明來自 Boris's Blogs

評論
avatar
Boris Chien
網頁前後端開發搭配實作的技術文章與生活紀錄,技術隨筆 https://hackmd.io/@monkeymonkey
Github上找到我
公告
喜歡資訊開發🖥,動手組裝🛠
\ No newline at end of file +}
\ No newline at end of file diff --git "a/(\346\212\200\350\241\223)\347\266\262\351\240\201\346\211\223\345\214\205\345\243\223\347\270\256\347\232\204\345\245\275\347\224\250\345\267\245\345\205\267Parcel/index.html" "b/(\346\212\200\350\241\223)\347\266\262\351\240\201\346\211\223\345\214\205\345\243\223\347\270\256\347\232\204\345\245\275\347\224\250\345\267\245\345\205\267Parcel/index.html" index 957175f8..fa8cab78 100644 --- "a/(\346\212\200\350\241\223)\347\266\262\351\240\201\346\211\223\345\214\205\345\243\223\347\270\256\347\232\204\345\245\275\347\224\250\345\267\245\345\205\267Parcel/index.html" +++ "b/(\346\212\200\350\241\223)\347\266\262\351\240\201\346\211\223\345\214\205\345\243\223\347\270\256\347\232\204\345\245\275\347\224\250\345\267\245\345\205\267Parcel/index.html" @@ -123,7 +123,7 @@ } } detectApple() - })(window)

(技術)網頁打包壓縮的好用工具Parcel

說到打包工具,多數人的第一直覺就是Webpack,我也不例外,今天就要介紹一個簡單快速的打包工具Parcel,適用於小型專案的開發。

為何壓縮

伺服器中,會使用壓縮來減少頻寬和傳輸時間,從而提高網站性能和用戶體驗。通常壓縮的是返回給客戶端的HTML、CSS、JavaScript、圖像等靜態資源文件。透過減少文件大小。

網頁伺服器會使用一些壓縮算法,例如gzip和deflate,將靜態資源文件壓縮成壓縮包,然後在將壓縮包傳輸給客戶端。客戶端接收到壓縮包後,會解壓縮文件並顯示頁面。

壓縮技術可以提高網站性能,但壓縮也可能增加服務器的負擔和處理時間。此外,某些瀏覽器不支持特定的壓縮算法,因此需要在服務器端進行相應的配置和優化。

原生性能

Parcel’s JavaScript compiler, CSS transformer, and source maps implementation are written in Rust for maximum performance. It’s 10-20x faster than other JavaScript-based tools!
Parcel’s JavaScript compiler is built on SWC, which handles transpiling JavaScript, JSX, and TypeScript. On top of SWC, Parcel implements dependency collection, bundling, scope hoisting, tree shaking, Node emulation, hot reloading, and more.
Parcel’s CSS transformer and minifier is built in Rust on top of the browser-grade CSS parser used in Firefox. It’s over 100x faster than other JavaScript-based transformers and minifiers.

JavaScript 編譯器、CSS 轉換器和源映射實現是用Rust編寫的,以實現最佳性能。它比其他基於 JavaScript 的工具快 10-20 倍!
Parcel 的 JavaScript 編譯器建立在SWC之上,它處理轉譯 JavaScript、JSX 和 TypeScript。在 SWC 之上,Parcel 實現了依賴收集、捆綁、範圍提升、tree shaking、Node 仿真、熱重載等。
Parcel 的 CSS 轉換器和縮小器是在 Firefox 中使用的瀏覽器級 CSS 解析器之上的 Rust 中構建的。比其他JavaScript 的轉換器和壓縮器快 100 倍以上。

快取

Everything Parcel does is cached – transformation, dependency resolution, bundling, optimizing, and everything in between. This means the dev server restarts instantly, and the same code is never built twice.
Parcel automatically tracks all of the files, configuration, plugins, and dev dependencies that are involved in your build, and granularly invalidates the cache when something changes. It integrates with low-level operating system APIs to determine what files have changed in milliseconds, no matter the project size.

Parcel 所做的一切都被緩存——轉換、依賴解析、捆綁、優化,以及介於兩者之間的一切。這意味著開發伺服器會立即重新啟動,並且永遠不會構建相同的代碼兩次。
自動追蹤構建中所有文件、配置、插件和依賴項,並在變化時使緩存失效。與低階操作系統 API 整合,無論項目大小如何,都可以在幾毫秒內確定哪些文件發生了變化。

安裝

1
npm install --save-dev parcel

配置

1
2
3
4
5
6
7
8
9
10
11
{
"name": "my-project",
"source": "src/index.html",
"scripts": {
"start": "parcel",
"build": "parcel build"
},
"devDependencies": {
"parcel": "latest"
}
}

資料夾

1
2
3
4
5
6
7
8
9
10
my-app/
|- dist/ # 編譯後代碼
| |- index.html # 打包後的 HTML
| |- main.js # 打包後的 JavaScript
|- node_modules/ # 第三方庫
|- src/ # 源碼
| |- index.html # HTML 入口
| |- main.js # JavaScript 入口
|- package.json # 配置
|-.parcel-cache # 打包緩存

開發環境
生產環境

JavaScript

介紹Parcel中js的配置前,先了解ES modules跟 CommonJS 的差異。

載入

ES modules 使用 import 載入模組,而 CommonJS 使用 require 載入模組。ES modules 在運行時進行靜態解析,而 CommonJS 在運行時動態載入。

編譯

ES modules 在編譯時會進行預解析和標記,使得編譯器能夠在編譯時知道哪些模組需要載入,而 CommonJS 則是在運行時動態載入,因此需要進行動態解析和加載,相對於 ES modules 更耗費運行時的資源。

輸出

ES modules 使用 export 輸出模組,而 CommonJS 使用 module.exports 輸出模組。ES modules 可以直接將對象、函數等直接作為輸出,而 CommonJS 必須透過 module.exports 將需要輸出的對象或函數包裝成對象再進行輸出。

結論

總之,ES modules 是一種新的模組化,比起CommonJS,有更好的靜態解析能力,支持標記和預解析,並且可以在編譯時優化。然而,目前在瀏覽器中 ES modules 的支援度還不夠完善,需要透過轉譯或者 polyfill 來實現,而 CommonJS 則是在 Node.js 等環境中得到了廣泛的使用。

ES modules

add.js

1
2
3
export function add(a, b) {
return a + b;
}

sum.js

1
2
3
4
5
import {add} from './add.js';

export function sum(x,y) {
return add(x, y);
}

CommonJS

add.js

1
2
3
exports.add=function(a, b) {
return a + b;
}

sum.js

1
2
3
4
5
const add=require('./add.js');

exports.sum=function(x,y) {
return add(x, y);
}

總結

與Webpack相比,Parcel的生態和功能有限,較難進行進階的設置。因此,在選擇使用Webpack還是Parcel時,需要根據具體需求和技術做出選擇。如果是在簡單項目中快速構建和開發,Parcel可能是一個不錯的選擇;如果需要更高度的客製化和擴展性,Webpack可能更符合需求。

參考資料

Parcel

文章作者: Boris Chien
文章連結: https://www.boris.idv.tw/(%E6%8A%80%E8%A1%93)%E7%B6%B2%E9%A0%81%E6%89%93%E5%8C%85%E5%A3%93%E7%B8%AE%E7%9A%84%E5%A5%BD%E7%94%A8%E5%B7%A5%E5%85%B7Parcel/
版權聲明: 本部落格所有文章除特別聲明外,均採用 CC BY-NC-SA 4.0 許可協議。轉載請註明來自 Boris's Blogs

評論

(技術)網頁打包壓縮的好用工具Parcel

說到打包工具,多數人的第一直覺就是Webpack,我也不例外,今天就要介紹一個簡單快速的打包工具Parcel,適用於小型專案的開發。

為何壓縮

伺服器中,會使用壓縮來減少頻寬和傳輸時間,從而提高網站性能和用戶體驗。通常壓縮的是返回給客戶端的HTML、CSS、JavaScript、圖像等靜態資源文件。透過減少文件大小。

網頁伺服器會使用一些壓縮算法,例如gzip和deflate,將靜態資源文件壓縮成壓縮包,然後在將壓縮包傳輸給客戶端。客戶端接收到壓縮包後,會解壓縮文件並顯示頁面。

壓縮技術可以提高網站性能,但壓縮也可能增加服務器的負擔和處理時間。此外,某些瀏覽器不支持特定的壓縮算法,因此需要在服務器端進行相應的配置和優化。

原生性能

Parcel’s JavaScript compiler, CSS transformer, and source maps implementation are written in Rust for maximum performance. It’s 10-20x faster than other JavaScript-based tools!
Parcel’s JavaScript compiler is built on SWC, which handles transpiling JavaScript, JSX, and TypeScript. On top of SWC, Parcel implements dependency collection, bundling, scope hoisting, tree shaking, Node emulation, hot reloading, and more.
Parcel’s CSS transformer and minifier is built in Rust on top of the browser-grade CSS parser used in Firefox. It’s over 100x faster than other JavaScript-based transformers and minifiers.

JavaScript 編譯器、CSS 轉換器和源映射實現是用Rust編寫的,以實現最佳性能。它比其他基於 JavaScript 的工具快 10-20 倍!
Parcel 的 JavaScript 編譯器建立在SWC之上,它處理轉譯 JavaScript、JSX 和 TypeScript。在 SWC 之上,Parcel 實現了依賴收集、捆綁、範圍提升、tree shaking、Node 仿真、熱重載等。
Parcel 的 CSS 轉換器和縮小器是在 Firefox 中使用的瀏覽器級 CSS 解析器之上的 Rust 中構建的。比其他JavaScript 的轉換器和壓縮器快 100 倍以上。

快取

Everything Parcel does is cached – transformation, dependency resolution, bundling, optimizing, and everything in between. This means the dev server restarts instantly, and the same code is never built twice.
Parcel automatically tracks all of the files, configuration, plugins, and dev dependencies that are involved in your build, and granularly invalidates the cache when something changes. It integrates with low-level operating system APIs to determine what files have changed in milliseconds, no matter the project size.

Parcel 所做的一切都被緩存——轉換、依賴解析、捆綁、優化,以及介於兩者之間的一切。這意味著開發伺服器會立即重新啟動,並且永遠不會構建相同的代碼兩次。
自動追蹤構建中所有文件、配置、插件和依賴項,並在變化時使緩存失效。與低階操作系統 API 整合,無論項目大小如何,都可以在幾毫秒內確定哪些文件發生了變化。

安裝

1
npm install --save-dev parcel

配置

1
2
3
4
5
6
7
8
9
10
11
{
"name": "my-project",
"source": "src/index.html",
"scripts": {
"start": "parcel",
"build": "parcel build"
},
"devDependencies": {
"parcel": "latest"
}
}

資料夾

1
2
3
4
5
6
7
8
9
10
my-app/
|- dist/ # 編譯後代碼
| |- index.html # 打包後的 HTML
| |- main.js # 打包後的 JavaScript
|- node_modules/ # 第三方庫
|- src/ # 源碼
| |- index.html # HTML 入口
| |- main.js # JavaScript 入口
|- package.json # 配置
|-.parcel-cache # 打包緩存

開發環境
生產環境

JavaScript

介紹Parcel中js的配置前,先了解ES modules跟 CommonJS 的差異。

載入

ES modules 使用 import 載入模組,而 CommonJS 使用 require 載入模組。ES modules 在運行時進行靜態解析,而 CommonJS 在運行時動態載入。

編譯

ES modules 在編譯時會進行預解析和標記,使得編譯器能夠在編譯時知道哪些模組需要載入,而 CommonJS 則是在運行時動態載入,因此需要進行動態解析和加載,相對於 ES modules 更耗費運行時的資源。

輸出

ES modules 使用 export 輸出模組,而 CommonJS 使用 module.exports 輸出模組。ES modules 可以直接將對象、函數等直接作為輸出,而 CommonJS 必須透過 module.exports 將需要輸出的對象或函數包裝成對象再進行輸出。

結論

總之,ES modules 是一種新的模組化,比起CommonJS,有更好的靜態解析能力,支持標記和預解析,並且可以在編譯時優化。然而,目前在瀏覽器中 ES modules 的支援度還不夠完善,需要透過轉譯或者 polyfill 來實現,而 CommonJS 則是在 Node.js 等環境中得到了廣泛的使用。

ES modules

add.js

1
2
3
export function add(a, b) {
return a + b;
}

sum.js

1
2
3
4
5
import {add} from './add.js';

export function sum(x,y) {
return add(x, y);
}

CommonJS

add.js

1
2
3
exports.add=function(a, b) {
return a + b;
}

sum.js

1
2
3
4
5
const add=require('./add.js');

exports.sum=function(x,y) {
return add(x, y);
}

總結

與Webpack相比,Parcel的生態和功能有限,較難進行進階的設置。因此,在選擇使用Webpack還是Parcel時,需要根據具體需求和技術做出選擇。如果是在簡單項目中快速構建和開發,Parcel可能是一個不錯的選擇;如果需要更高度的客製化和擴展性,Webpack可能更符合需求。

參考資料

Parcel

文章作者: Boris Chien
文章連結: https://www.boris.idv.tw/(%E6%8A%80%E8%A1%93)%E7%B6%B2%E9%A0%81%E6%89%93%E5%8C%85%E5%A3%93%E7%B8%AE%E7%9A%84%E5%A5%BD%E7%94%A8%E5%B7%A5%E5%85%B7Parcel/
版權聲明: 本部落格所有文章除特別聲明外,均採用 CC BY-NC-SA 4.0 許可協議。轉載請註明來自 Boris's Blogs

評論
\ No newline at end of file +}
\ No newline at end of file diff --git "a/(\346\212\200\350\241\223)\350\243\275\344\275\234\350\207\252\345\213\225\346\216\222\347\250\213\347\232\204YoubikeLineBot/index.html" "b/(\346\212\200\350\241\223)\350\243\275\344\275\234\350\207\252\345\213\225\346\216\222\347\250\213\347\232\204YoubikeLineBot/index.html" index a3b1e715..b76d5ae6 100644 --- "a/(\346\212\200\350\241\223)\350\243\275\344\275\234\350\207\252\345\213\225\346\216\222\347\250\213\347\232\204YoubikeLineBot/index.html" +++ "b/(\346\212\200\350\241\223)\350\243\275\344\275\234\350\207\252\345\213\225\346\216\222\347\250\213\347\232\204YoubikeLineBot/index.html" @@ -123,7 +123,7 @@ } } detectApple() - })(window)

(技術)製作自動排程的YoubikeLineBot

關於騎腳踏車上班

Youbike 通勤上下班,趕到公司樓下卻發現沒有空位,只能花費雙倍路程時間步行到上一站,搜尋可行的解決方案,別人製作的 站點地圖是不錯的解決方案,但對壓線出門的懶人不是最佳解,重複的查詢、比較、紀錄相當多餘,真正能解決痛點的是固定時間、主動通知、快速查詢工具。
以 Node.js開發的 bot,邏輯在index.js完整原始碼

特點

  • 自動化查詢
  • 部署Render雲服務
  • 排程每日通知

SDK

其他語言參考Official SDKs,官方提供

  • Java
  • PHP
  • Go
  • Perl
  • Ruby
  • Python
  • Node.js

本地

1
git clone https://github.com/chienniman/YouBikeNotify-Bot.git
1
npm install
1
mkdir .env

環境變數&金鑰

Cron

1
npm install --save node-cron

臺中交通資訊 API

上網搜了一下發現臺中交通資訊 API 整合的相當不錯,Swagger 的文件架構清晰,井然有序,這邊給個讚,台中路面狀況如果也可以就謝天謝地了
臺中交通資訊 API

LINE Developers

首先要先創建一個 LINE Developers 帳號
註冊網址

LINE Bot channel

登入後點選 Create new channel 創建新的 LINE Bot 頻道,並且填寫頻道相關資訊(例如:頻道名稱、頻道圖片、類型等等)。

ngrok

ngrok 做為一個轉發的伺服器,他可以把外界的請求轉發到你指定的 Port,使用的背景原理是連接到 ngrok 雲端伺服器,將你本機指定的地址公開,再將由 ngrok 一串公開的網址來存取內容。他的優點是快速而且還提供了 https 的服務讓你使用上更安全,甚至你還可以設置密碼保護。

ref-[Day-37] 使用 ngrok 讓外網連接你的 API

安裝

ngrok

執行

windows,雙擊 exe

linux, cd ngrok

1
ngrok.exe http {port}

映射

1
2
<!-- 雲端=>本地 -->
Forwarding https://xxxxxx.ngrok.io -> localhost:{port}

資安

沒有正確地設定 ngrok,防火牆、密碼,可能導致安全風險,使用完記得ctrl+c退出

驗證失敗

ngrok 運行 500,terminal 顯示 404,因為 token 沒設定好

部署雲端

官方文件nodejs-on-rende

1.設定render.yaml
2.新增 Web Service
3.Public Git repository
4.設定姓名、環境、區域
5.編譯部屬成功
deploy-success

免費限制

Free instance types are not available for Private Services, Background Workers, or Cron Jobs.

Web Services on the free instance type are automatically spun down after 15 minutes of inactivity. When a new request for a free service comes in, Render spins it up again so it can process the request.
This can cause a response delay of up to 30 seconds for the first request that comes in after a period of inactivity.

  • 本地伺服器可自動排程,但 render 雲的免費計畫不支援
  • 超過 15 分鐘沒有活動,伺服器會自動停止,直到新的請求,造成延遲響應。

心得

youbike 地圖相當方便,但是查詢、紀錄、比較等重複性工作仍可優化,都說科技始終來自惰性,有了排程查詢機器人後只需要被動等待通知,但缺點也是相當明顯,不穩定的響應(1 秒~6 分鐘),注定讓免費計畫只能作為實驗用途,很少使用者能接受超過 5 秒的等待,會不會升級成付費版本目前還在觀察中。

文章作者: Boris Chien
文章連結: https://www.boris.idv.tw/(%E6%8A%80%E8%A1%93)%E8%A3%BD%E4%BD%9C%E8%87%AA%E5%8B%95%E6%8E%92%E7%A8%8B%E7%9A%84YoubikeLineBot/
版權聲明: 本部落格所有文章除特別聲明外,均採用 CC BY-NC-SA 4.0 許可協議。轉載請註明來自 Boris's Blogs

評論

(技術)製作自動排程的YoubikeLineBot

關於騎腳踏車上班

Youbike 通勤上下班,趕到公司樓下卻發現沒有空位,只能花費雙倍路程時間步行到上一站,搜尋可行的解決方案,別人製作的 站點地圖是不錯的解決方案,但對壓線出門的懶人不是最佳解,重複的查詢、比較、紀錄相當多餘,真正能解決痛點的是固定時間、主動通知、快速查詢工具。
以 Node.js開發的 bot,邏輯在index.js完整原始碼

特點

  • 自動化查詢
  • 部署Render雲服務
  • 排程每日通知

SDK

其他語言參考Official SDKs,官方提供

  • Java
  • PHP
  • Go
  • Perl
  • Ruby
  • Python
  • Node.js

本地

1
git clone https://github.com/chienniman/YouBikeNotify-Bot.git
1
npm install
1
mkdir .env

環境變數&金鑰

Cron

1
npm install --save node-cron

臺中交通資訊 API

上網搜了一下發現臺中交通資訊 API 整合的相當不錯,Swagger 的文件架構清晰,井然有序,這邊給個讚,台中路面狀況如果也可以就謝天謝地了
臺中交通資訊 API

LINE Developers

首先要先創建一個 LINE Developers 帳號
註冊網址

LINE Bot channel

登入後點選 Create new channel 創建新的 LINE Bot 頻道,並且填寫頻道相關資訊(例如:頻道名稱、頻道圖片、類型等等)。

ngrok

ngrok 做為一個轉發的伺服器,他可以把外界的請求轉發到你指定的 Port,使用的背景原理是連接到 ngrok 雲端伺服器,將你本機指定的地址公開,再將由 ngrok 一串公開的網址來存取內容。他的優點是快速而且還提供了 https 的服務讓你使用上更安全,甚至你還可以設置密碼保護。

ref-[Day-37] 使用 ngrok 讓外網連接你的 API

安裝

ngrok

執行

windows,雙擊 exe

linux, cd ngrok

1
ngrok.exe http {port}

映射

1
2
<!-- 雲端=>本地 -->
Forwarding https://xxxxxx.ngrok.io -> localhost:{port}

資安

沒有正確地設定 ngrok,防火牆、密碼,可能導致安全風險,使用完記得ctrl+c退出

驗證失敗

ngrok 運行 500,terminal 顯示 404,因為 token 沒設定好

部署雲端

官方文件nodejs-on-rende

1.設定render.yaml
2.新增 Web Service
3.Public Git repository
4.設定姓名、環境、區域
5.編譯部屬成功
deploy-success

免費限制

Free instance types are not available for Private Services, Background Workers, or Cron Jobs.

Web Services on the free instance type are automatically spun down after 15 minutes of inactivity. When a new request for a free service comes in, Render spins it up again so it can process the request.
This can cause a response delay of up to 30 seconds for the first request that comes in after a period of inactivity.

  • 本地伺服器可自動排程,但 render 雲的免費計畫不支援
  • 超過 15 分鐘沒有活動,伺服器會自動停止,直到新的請求,造成延遲響應。

心得

youbike 地圖相當方便,但是查詢、紀錄、比較等重複性工作仍可優化,都說科技始終來自惰性,有了排程查詢機器人後只需要被動等待通知,但缺點也是相當明顯,不穩定的響應(1 秒~6 分鐘),注定讓免費計畫只能作為實驗用途,很少使用者能接受超過 5 秒的等待,會不會升級成付費版本目前還在觀察中。

文章作者: Boris Chien
文章連結: https://www.boris.idv.tw/(%E6%8A%80%E8%A1%93)%E8%A3%BD%E4%BD%9C%E8%87%AA%E5%8B%95%E6%8E%92%E7%A8%8B%E7%9A%84YoubikeLineBot/
版權聲明: 本部落格所有文章除特別聲明外,均採用 CC BY-NC-SA 4.0 許可協議。轉載請註明來自 Boris's Blogs

評論
\ No newline at end of file +}
\ No newline at end of file diff --git "a/(\346\212\200\350\241\223)\351\200\217\351\201\216Github-Action\345\257\246\347\217\276CICD-Pipeline/index.html" "b/(\346\212\200\350\241\223)\351\200\217\351\201\216Github-Action\345\257\246\347\217\276CICD-Pipeline/index.html" index 28ffcdee..ee9559ea 100644 --- "a/(\346\212\200\350\241\223)\351\200\217\351\201\216Github-Action\345\257\246\347\217\276CICD-Pipeline/index.html" +++ "b/(\346\212\200\350\241\223)\351\200\217\351\201\216Github-Action\345\257\246\347\217\276CICD-Pipeline/index.html" @@ -1,4 +1,4 @@ -(技術)透過Github-Action實現CICD-Pipeline | Boris's Blogs

(技術)透過Github-Action實現CICD-Pipeline

How to use

  • git clone

    1
    https://github.com/chienniman/mantine-vite-template.git
  • download the ZIP

  • fork the project

Create a new repository

Selected Public to host free gh-page app

Create CI/CD workflow

.github /workflows/main.yml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
name: Deploy to gh-page
permissions:
contents: write
on:
push:
branches: master

jobs:
build:
name: Build
runs-on: ubuntu-latest

steps:
- name: Checkout repo
uses: actions/checkout@v3

- name: Setup Node
uses: actions/setup-node@v2

- name: CI
run: npm ci

- name: Typecheck
run: npm run typecheck

- name: Prettier
run: npm run prettier

- name: Lint
run: npm run lint

- name: Jest
run: npm run jest

- name: Run build
run: npm run build

- name: Upload production-ready build files
uses: actions/upload-artifact@v2
with:
name: production-files
path: ./dist

deploy:
name: Deploy
needs: build
runs-on: ubuntu-latest
if: github.ref == 'refs/heads/master'

steps:
- name: Download artifact
uses: actions/download-artifact@v2
with:
name: production-files
path: ./dist

- name: Deploy to gh-pages
uses: peaceiris/actions-gh-pages@v3
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
publish_dir: ./dist

Local development and usage

install yarn

1
yarn --version
1
npm install --global yarn

install node_modules

1
yarn install

add homepage to package.json

1
"homepage": "https://<githubusername>.github.io/<app>"

Start the vite server and develop new features.

1
npm run dev

test

1
npm run test

Commit to master branch

1
2
3
git init
git add .
git commit -m "xxx"

Enable GitHub Pages

The source must be set to gh-pages instead of master/main, otherwise it will not be displayed.

Done

Discussion

To fix the issue of resource loading 404 errors and modify the default path, you can achieve it through the configuration in vite.config.ts.

vite.config.ts

1
2
3
4
5
6
7
8
9
10
11
12
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';

// https://vitejs.dev/config/
export default defineConfig({
plugins: [react()],
base: '/mantine-vite-template/',
build: {
assetsDir: 'assets',
},
});

Pages build and deployment

I think there’s a lot of scope for confusion for users of this action, when pages build and deployment will also be running on every push and pushing pages assets.

I think it’s impossible to really say right now what that looks like until GitHub announces what these actions intend to do in the long run. As the post suggests this is a necessary step that occurs after the push gets made, this was already occurring behind the scenes it just wasn’t made visible.

Ref

yarn
What is actions/checkout@v2 in Github action
deploy-to-github-pages
vite-deploy-demo
antonputra/tutorials
github-pages-deploy-action

文章作者: Boris Chien
文章連結: https://www.boris.idv.tw/(%E6%8A%80%E8%A1%93)%E9%80%8F%E9%81%8EGithub-Action%E5%AF%A6%E7%8F%BECICD-Pipeline/
版權聲明: 本部落格所有文章除特別聲明外,均採用 CC BY-NC-SA 4.0 許可協議。轉載請註明來自 Boris's Blogs

評論

(技術)透過Github-Action實現CICD-Pipeline

How to use

  • git clone
1
https://github.com/chienniman/mantine-vite-template.git
  • download the ZIP

  • fork the project

Create a new repository

Selected Public to host free gh-page app

Create CI/CD workflow

.github /workflows/main.yml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
name: Deploy to gh-page
permissions:
contents: write
on:
push:
branches: master

jobs:
build:
name: Build
runs-on: ubuntu-latest

steps:
- name: Checkout repo
uses: actions/checkout@v3

- name: Setup Node
uses: actions/setup-node@v2

- name: CI
run: npm ci

- name: Typecheck
run: npm run typecheck

- name: Prettier
run: npm run prettier

- name: Lint
run: npm run lint

- name: Jest
run: npm run jest

- name: Run build
run: npm run build

- name: Upload production-ready build files
uses: actions/upload-artifact@v2
with:
name: production-files
path: ./dist

deploy:
name: Deploy
needs: build
runs-on: ubuntu-latest
if: github.ref == 'refs/heads/master'

steps:
- name: Download artifact
uses: actions/download-artifact@v2
with:
name: production-files
path: ./dist

- name: Deploy to gh-pages
uses: peaceiris/actions-gh-pages@v3
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
publish_dir: ./dist

Local development and usage

install yarn

1
yarn --version
1
npm install --global yarn

install node_modules

1
yarn install

add homepage to package.json

1
"homepage": "https://<githubusername>.github.io/<app>"

Start the vite server and develop new features.

1
npm run dev

test

1
npm run test

Commit to master branch

1
2
3
git init
git add .
git commit -m "xxx"

Enable GitHub Pages

The source must be set to gh-pages instead of master/main, otherwise it will not be displayed.

Done

Discussion

To fix the issue of resource loading 404 errors and modify the default path, you can achieve it through the configuration in vite.config.ts.

vite.config.ts

1
2
3
4
5
6
7
8
9
10
11
12
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';

// https://vitejs.dev/config/
export default defineConfig({
plugins: [react()],
base: '/mantine-vite-template/',
build: {
assetsDir: 'assets',
},
});

Pages build and deployment

I think there’s a lot of scope for confusion for users of this action, when pages build and deployment will also be running on every push and pushing pages assets.

I think it’s impossible to really say right now what that looks like until GitHub announces what these actions intend to do in the long run. As the post suggests this is a necessary step that occurs after the push gets made, this was already occurring behind the scenes it just wasn’t made visible.

Ref

yarn
What is actions/checkout@v2 in Github action
deploy-to-github-pages
vite-deploy-demo
antonputra/tutorials
github-pages-deploy-action

文章作者: Boris Chien
文章連結: https://www.boris.idv.tw/(%E6%8A%80%E8%A1%93)%E9%80%8F%E9%81%8EGithub-Action%E5%AF%A6%E7%8F%BECICD-Pipeline/
版權聲明: 本部落格所有文章除特別聲明外,均採用 CC BY-NC-SA 4.0 許可協議。轉載請註明來自 Boris's Blogs

評論
\ No newline at end of file +}
\ No newline at end of file diff --git "a/(\351\201\212\346\210\262)\344\270\215\351\235\240T\350\275\211\350\267\237\345\256\214\347\276\216\346\266\210\351\231\244\351\201\224\345\210\260TETR\347\232\204S\347\211\214\344\275\215/index.html" "b/(\351\201\212\346\210\262)\344\270\215\351\235\240T\350\275\211\350\267\237\345\256\214\347\276\216\346\266\210\351\231\244\351\201\224\345\210\260TETR\347\232\204S\347\211\214\344\275\215/index.html" index 634d29e9..9b44b01e 100644 --- "a/(\351\201\212\346\210\262)\344\270\215\351\235\240T\350\275\211\350\267\237\345\256\214\347\276\216\346\266\210\351\231\244\351\201\224\345\210\260TETR\347\232\204S\347\211\214\344\275\215/index.html" +++ "b/(\351\201\212\346\210\262)\344\270\215\351\235\240T\350\275\211\350\267\237\345\256\214\347\276\216\346\266\210\351\231\244\351\201\224\345\210\260TETR\347\232\204S\347\211\214\344\275\215/index.html" @@ -1,4 +1,4 @@ -(遊戲)不靠T轉跟完美消除達到TETR的S牌位 | Boris's Blogs

(遊戲)不靠T轉跟完美消除達到TETR的S牌位

2022 年因為伺服器延遲問題從特戰英豪退坑後,每周零零散散的玩幾場 CSGO 競技,不得不說在基建的部分,V 社做得比拳頭好很多,像特戰英豪這種高強度競技射擊,PING 飆到 200、300 基本上走出去就被爆頭了(白金~鑽石),無遊戲體驗可言,心灰意冷轉戰 2021 年時發現的俄羅斯方塊,沒有搞氣氛的隊友,沒有馬鈴薯伺服器,勝負大機率取決於個人技巧。

介紹兩個特殊技巧,T 轉(T-Spin)完美消除(Perfect Clear)

完美消除(Perfect Clear)

透過特殊擺法消除場上所有方塊,不包含垃圾

開場造成 10 行以上的攻擊(取決於 B2B combo),非常致命

T-Spin

顧名思義,透過旋轉 T 方塊的特殊消行技巧,每個遊戲有不同計算方式,以下是 4 個 T-spin Triple 加上一個 mini single 的示範

牌位

D~C+

先贏 3 場,入門級,速度緩慢,失誤多,方塊擺放不整齊就開始消行,注重自身的防守。

B-~B+

先贏 3 場,頻繁使用連招,小失誤,比拚消行速度與時機點把握,推薦空 2、3 行,重點在懲罰對手的失誤。

A-~A+

先贏 3 場,實力落差大,不穩定的玩家在 B+~A-震盪,穩定型會在 A+卡一陣子,專注於B2B Combo,雙方基本不失誤,差別於爆發總量,受到手感跟方塊擺放邏輯影響,不能有明顯弱點,方塊高低起伏過大、速度偏慢、COMBO 少、小失誤,容易被一波帶走。

S-~SS

先贏 5場,T 轉跟完美消除是基本盤,手感、運氣下滑或 B2B Combo 中斷,被打亂節奏,高處被卡死是家常便飯。

爆發型

開局連續 T 轉、完美消除使對手來不及疊高 Combo 就被 KO

優點

  • 前期優勢
  • 方塊高度低

缺點

  • 手感、運氣差容易被懲罰
  • 過度依賴於特定方塊
  • 容錯率低

穩定型

持續疊高,留 1~3 空行

優點

  • 一行能保持 B2B Combo,二到三行能在後期大量轟炸
  • 容錯高,堆疊快
  • 可攻可守

缺點

  • 爆發總行少
  • 開局劣勢

S 級有不少手速快到令人咋舌的玩家,但還是能透過合理分析,選用策略來增加勝率,在開場時觀察,如果發現對手擺放固定套路,準備完美消除或是連續 T 轉,進行Quad(4 消行)循環,保持 B2B Combo(不參雜單、雙、三消行),能帶來額外的攻擊行數,對T轉苦手很有幫助。
對手將方塊疊高,留 1~3 行,短時間大量轟炸,如果自身手感下滑,建議將地基打掉扛住這波爆發,順著對手的步調走硬碰硬,因為對手的輸出總量等於自身累積+消除垃圾行,沒有足夠的行數抵銷,容易陷入劣勢。

總結

Tetr 鼓勵使用不中斷的 T 轉或是 Quad,不崇尚單消行防守,這點可以從B2B Combo累計表看出,曾經風靡一時的臉書遊戲Tetris Battle,會在KO數相同時比較總消行數,但Tetr只考慮誰先取得足夠勝場,前期消行慢,仔細思考布置也是一種遊戲風格,帶來更大的自由性,不會因前期劣勢滾雪球,導致不可挽回的敗北。

文章作者: Boris Chien
文章連結: https://www.boris.idv.tw/(%E9%81%8A%E6%88%B2)%E4%B8%8D%E9%9D%A0T%E8%BD%89%E8%B7%9F%E5%AE%8C%E7%BE%8E%E6%B6%88%E9%99%A4%E9%81%94%E5%88%B0TETR%E7%9A%84S%E7%89%8C%E4%BD%8D/
版權聲明: 本部落格所有文章除特別聲明外,均採用 CC BY-NC-SA 4.0 許可協議。轉載請註明來自 Boris's Blogs

評論

(遊戲)不靠T轉跟完美消除達到TETR的S牌位

2022 年因為伺服器延遲問題從特戰英豪退坑後,每周零零散散的玩幾場 CSGO 競技,不得不說在基建的部分,V 社做得比拳頭好很多,像特戰英豪這種高強度競技射擊,PING 飆到 200、300 基本上走出去就被爆頭了(白金~鑽石),無遊戲體驗可言,心灰意冷轉戰 2021 年時發現的俄羅斯方塊,沒有搞氣氛的隊友,沒有馬鈴薯伺服器,勝負大機率取決於個人技巧。

介紹兩個特殊技巧,T 轉(T-Spin)完美消除(Perfect Clear)

完美消除(Perfect Clear)

透過特殊擺法消除場上所有方塊,不包含垃圾

開場造成 10 行以上的攻擊(取決於 B2B combo),非常致命

T-Spin

顧名思義,透過旋轉 T 方塊的特殊消行技巧,每個遊戲有不同計算方式,以下是 4 個 T-spin Triple 加上一個 mini single 的示範

牌位

D~C+

先贏 3 場,入門級,速度緩慢,失誤多,方塊擺放不整齊就開始消行,注重自身的防守。

B-~B+

先贏 3 場,頻繁使用連招,小失誤,比拚消行速度與時機點把握,推薦空 2、3 行,重點在懲罰對手的失誤。

A-~A+

先贏 3 場,實力落差大,不穩定的玩家在 B+~A-震盪,穩定型會在 A+卡一陣子,專注於B2B Combo,雙方基本不失誤,差別於爆發總量,受到手感跟方塊擺放邏輯影響,不能有明顯弱點,方塊高低起伏過大、速度偏慢、COMBO 少、小失誤,容易被一波帶走。

S-~SS

先贏 5場,T 轉跟完美消除是基本盤,手感、運氣下滑或 B2B Combo 中斷,被打亂節奏,高處被卡死是家常便飯。

爆發型

開局連續 T 轉、完美消除使對手來不及疊高 Combo 就被 KO

優點

  • 前期優勢
  • 方塊高度低

缺點

  • 手感、運氣差容易被懲罰
  • 過度依賴於特定方塊
  • 容錯率低

穩定型

持續疊高,留 1~3 空行

優點

  • 一行能保持 B2B Combo,二到三行能在後期大量轟炸
  • 容錯高,堆疊快
  • 可攻可守

缺點

  • 爆發總行少
  • 開局劣勢

S 級有不少手速快到令人咋舌的玩家,但還是能透過合理分析,選用策略來增加勝率,在開場時觀察,如果發現對手擺放固定套路,準備完美消除或是連續 T 轉,進行Quad(4 消行)循環,保持 B2B Combo(不參雜單、雙、三消行),能帶來額外的攻擊行數,對T轉苦手很有幫助。
對手將方塊疊高,留 1~3 行,短時間大量轟炸,如果自身手感下滑,建議將地基打掉扛住這波爆發,順著對手的步調走硬碰硬,因為對手的輸出總量等於自身累積+消除垃圾行,沒有足夠的行數抵銷,容易陷入劣勢。

總結

Tetr 鼓勵使用不中斷的 T 轉或是 Quad,不崇尚單消行防守,這點可以從B2B Combo累計表看出,曾經風靡一時的臉書遊戲Tetris Battle,會在KO數相同時比較總消行數,但Tetr只考慮誰先取得足夠勝場,前期消行慢,仔細思考布置也是一種遊戲風格,帶來更大的自由性,不會因前期劣勢滾雪球,導致不可挽回的敗北。

文章作者: Boris Chien
文章連結: https://www.boris.idv.tw/(%E9%81%8A%E6%88%B2)%E4%B8%8D%E9%9D%A0T%E8%BD%89%E8%B7%9F%E5%AE%8C%E7%BE%8E%E6%B6%88%E9%99%A4%E9%81%94%E5%88%B0TETR%E7%9A%84S%E7%89%8C%E4%BD%8D/
版權聲明: 本部落格所有文章除特別聲明外,均採用 CC BY-NC-SA 4.0 許可協議。轉載請註明來自 Boris's Blogs

評論
\ No newline at end of file +}
\ No newline at end of file diff --git "a/(\351\201\212\346\210\262)\347\215\250\350\207\252\346\256\262\346\273\20511\345\220\215PUBG\347\216\251\345\256\266\344\270\246\345\220\203\351\233\236/index.html" "b/(\351\201\212\346\210\262)\347\215\250\350\207\252\346\256\262\346\273\20511\345\220\215PUBG\347\216\251\345\256\266\344\270\246\345\220\203\351\233\236/index.html" new file mode 100644 index 00000000..f7666e56 --- /dev/null +++ "b/(\351\201\212\346\210\262)\347\215\250\350\207\252\346\256\262\346\273\20511\345\220\215PUBG\347\216\251\345\256\266\344\270\246\345\220\203\351\233\236/index.html" @@ -0,0 +1,156 @@ +(遊戲)獨自殲滅11名PUBG玩家並吃雞 | Boris's Blogs

(遊戲)獨自殲滅11名PUBG玩家並吃雞

(遊戲)獨自殲滅11名PUBG玩家並吃雞

開放免費後,入坑 PUBG 兩個賽季了,對 LITE 沒有的武器感到新奇,Lynx AMR 反器材炮、P90 零後座衝鋒、MG3 異次元火力、Groza 近距步槍之王、Famas 遠距步槍之王、Dragunov 連發栓狙,但我最喜歡的還是 Beryl M762,高居第一位的非空投 DPS 五秒內能秒掉一隊。

超高輸出的代價就是超高後座力,選用補償器 + 水平握把能夠抵銷成 k2 的手感,頭線加上預開,100 等以前玩家隨便虐,策略上來說,採用壓線進圈,比起先進圈。

壓線進圈

優點

  • 抓跑圈仔屁股
  • 不擔心被後面偷襲
  • 槍法夠準滾人頭快

缺點

  • 害怕伏地魔
  • 害怕高位槍線
  • 對投擲物、藥品需求高

像我這種單人組四排的玩家,不太可能像戰隊直接在自閉城獵殺玩家,比較多的是掌握資訊後偷襲,想要一打多的策略是逐一擊破,從高位槍線逐一抓掉,封煙扶人立刻補手榴彈,低段位玩家不擅長使用投擲物,事實上這遊戲的掩體優勢並沒有如此巨大,只要手榴彈丟的夠準,沒掩體也不是大問題。

吃雞

這遊戲七成吃運氣,等待時隊友等級太低直接跳 game (不算戰績),運氣很背沒掩體又被刷出圈只能認了,有一種說法是空投會落在下一個圈內(未經證實),前期遊走在邊線抓人,後期在圈中心當伏地魔,選高地,選掩體,剩下交給時間跟運氣。

文章作者: Boris Chien
文章連結: https://www.boris.idv.tw/(%E9%81%8A%E6%88%B2)%E7%8D%A8%E8%87%AA%E6%AE%B2%E6%BB%8511%E5%90%8DPUBG%E7%8E%A9%E5%AE%B6%E4%B8%A6%E5%90%83%E9%9B%9E/
版權聲明: 本部落格所有文章除特別聲明外,均採用 CC BY-NC-SA 4.0 許可協議。轉載請註明來自 Boris's Blogs

評論
avatar
Boris Chien
網頁前後端開發搭配實作的技術文章與生活紀錄,技術隨筆 https://hackmd.io/@monkeymonkey
Github上找到我
公告
喜歡資訊開發🖥,動手組裝🛠
\ No newline at end of file diff --git a/about/index.html b/about/index.html index 8f1c65de..7d62f4d4 100644 --- a/about/index.html +++ b/about/index.html @@ -1,4 +1,4 @@ -技能 | Boris's Blogs

專業認證

Microsoft AZ900

IBM Python Project for Data Science

ISCB 資訊系統安全開發與驗證實務

Google 數位學程

技能

My Skills

Frontend

  • React/Mantine/Material-UI
  • HTML/CSS/JavaScript
  • Bootstrap/Tailwind
  • Webpack/Parcel

Backend

  • Laravel
  • PHP/Node.js
  • MySQL/SQL
  • Nginx/Linux
  • Docker
  • Websocket

CI/CD

  • Github action

VCS

  • Gitlab/Github/git

評論

專業認證

Microsoft AZ900

IBM Python Project for Data Science

ISCB 資訊系統安全開發與驗證實務

Google 數位學程

技能

My Skills

Frontend

  • React/Mantine/Material-UI
  • HTML/CSS/JavaScript
  • Bootstrap/Tailwind
  • Webpack/Parcel

Backend

  • Laravel
  • PHP/Node.js
  • MySQL/SQL
  • Nginx/Linux
  • Docker
  • Websocket

CI/CD

  • Github action

VCS

  • Gitlab/Github/git

評論
\ No newline at end of file +}
\ No newline at end of file diff --git a/archives/2023/02/index.html b/archives/2023/02/index.html index 4b555341..a00e8eda 100644 --- a/archives/2023/02/index.html +++ b/archives/2023/02/index.html @@ -38,7 +38,7 @@ toc: true, rightside: false, } -}
\ No newline at end of file + })(window)
\ No newline at end of file diff --git a/archives/2023/03/index.html b/archives/2023/03/index.html index 600fc141..5a7b0bde 100644 --- a/archives/2023/03/index.html +++ b/archives/2023/03/index.html @@ -38,7 +38,7 @@ toc: true, rightside: false, } -}
\ No newline at end of file + })(window)
\ No newline at end of file diff --git a/archives/2023/04/index.html b/archives/2023/04/index.html index 422bf775..677960ea 100644 --- a/archives/2023/04/index.html +++ b/archives/2023/04/index.html @@ -38,7 +38,7 @@ toc: true, rightside: false, } -}
\ No newline at end of file + })(window)
\ No newline at end of file diff --git a/archives/2023/05/index.html b/archives/2023/05/index.html index 840f6211..d706cec3 100644 --- a/archives/2023/05/index.html +++ b/archives/2023/05/index.html @@ -38,7 +38,7 @@ toc: true, rightside: false, } -}
\ No newline at end of file + })(window)
\ No newline at end of file diff --git a/archives/2023/06/index.html b/archives/2023/06/index.html index d7e52262..ea4a5d1f 100644 --- a/archives/2023/06/index.html +++ b/archives/2023/06/index.html @@ -38,7 +38,7 @@ toc: true, rightside: false, } -}
文章總覽 - 1
2023
(技術)透過Github-Action實現CICD-Pipeline
(技術)透過Github-Action實現CICD-Pipeline
\ No newline at end of file + })(window)
文章總覽 - 1
2023
(技術)透過Github-Action實現CICD-Pipeline
(技術)透過Github-Action實現CICD-Pipeline
\ No newline at end of file diff --git a/archives/2023/07/index.html b/archives/2023/07/index.html index f739e48a..69b6cbfd 100644 --- a/archives/2023/07/index.html +++ b/archives/2023/07/index.html @@ -38,7 +38,7 @@ toc: true, rightside: false, } -}
文章總覽 - 1
2023
(心得)Linda-Rising敏捷思維的力量
(心得)Linda-Rising敏捷思維的力量
\ No newline at end of file + })(window)
文章總覽 - 1
2023
(心得)Linda-Rising敏捷思維的力量
(心得)Linda-Rising敏捷思維的力量
\ No newline at end of file diff --git a/archives/2023/10/index.html b/archives/2023/10/index.html index 15082d6c..a4f2b144 100644 --- a/archives/2023/10/index.html +++ b/archives/2023/10/index.html @@ -38,7 +38,7 @@ toc: true, rightside: false, } -}
\ No newline at end of file + })(window)
\ No newline at end of file diff --git a/archives/2023/11/index.html b/archives/2023/11/index.html index 414e17db..468732d0 100644 --- a/archives/2023/11/index.html +++ b/archives/2023/11/index.html @@ -38,7 +38,7 @@ toc: true, rightside: false, } -}
文章總覽 - 1
2023
(技術)Laravel-Queue-訊息隊列
\ No newline at end of file + })(window)
文章總覽 - 1
2023
(技術)Laravel-Queue-訊息隊列
\ No newline at end of file diff --git a/archives/2023/12/index.html b/archives/2023/12/index.html new file mode 100644 index 00000000..7babfbe2 --- /dev/null +++ b/archives/2023/12/index.html @@ -0,0 +1,126 @@ +十二月 2023 | Boris's Blogs
文章總覽 - 1
2023
(遊戲)獨自殲滅11名PUBG玩家並吃雞
\ No newline at end of file diff --git a/archives/2023/index.html b/archives/2023/index.html index 1ff941b8..354f16e7 100644 --- a/archives/2023/index.html +++ b/archives/2023/index.html @@ -38,7 +38,7 @@ toc: true, rightside: false, } -}
\ No newline at end of file + })(window)
\ No newline at end of file diff --git a/archives/2023/page/2/index.html b/archives/2023/page/2/index.html index 7c57359a..6635cdb2 100644 --- a/archives/2023/page/2/index.html +++ b/archives/2023/page/2/index.html @@ -38,7 +38,7 @@ toc: true, rightside: false, } -}
\ No newline at end of file + })(window)
\ No newline at end of file diff --git a/archives/index.html b/archives/index.html index 174575e2..91590d37 100644 --- a/archives/index.html +++ b/archives/index.html @@ -38,7 +38,7 @@ toc: true, rightside: false, } -}
\ No newline at end of file + })(window)
\ No newline at end of file diff --git a/archives/page/2/index.html b/archives/page/2/index.html index 5ebaa3fd..3f5d533f 100644 --- a/archives/page/2/index.html +++ b/archives/page/2/index.html @@ -38,7 +38,7 @@ toc: true, rightside: false, } -}
\ No newline at end of file + })(window)
\ No newline at end of file diff --git a/categories/Backend/index.html b/categories/Backend/index.html index b3125400..82c91248 100644 --- a/categories/Backend/index.html +++ b/categories/Backend/index.html @@ -38,7 +38,7 @@ toc: true, rightside: false, } -}
\ No newline at end of file + })(window)
\ No newline at end of file diff --git a/categories/CI-CD/index.html b/categories/CI-CD/index.html index 09a4f760..7f0dbadb 100644 --- a/categories/CI-CD/index.html +++ b/categories/CI-CD/index.html @@ -38,7 +38,7 @@ toc: true, rightside: false, } -}
\ No newline at end of file + })(window)
\ No newline at end of file diff --git a/categories/Diary/index.html b/categories/Diary/index.html index 961a508f..9e8ffc42 100644 --- a/categories/Diary/index.html +++ b/categories/Diary/index.html @@ -38,7 +38,7 @@ toc: true, rightside: false, } -}
\ No newline at end of file + })(window)
\ No newline at end of file diff --git a/categories/Frontend/index.html b/categories/Frontend/index.html index 96374d69..26399459 100644 --- a/categories/Frontend/index.html +++ b/categories/Frontend/index.html @@ -38,7 +38,7 @@ toc: true, rightside: false, } -}
\ No newline at end of file + })(window)
\ No newline at end of file diff --git a/categories/Line-API/index.html b/categories/Line-API/index.html index 493873bf..eaf72eba 100644 --- a/categories/Line-API/index.html +++ b/categories/Line-API/index.html @@ -38,7 +38,7 @@ toc: true, rightside: false, } -}
分類 - Line API
2023
(技術)製作自動排程的YoubikeLineBot
(技術)製作自動排程的YoubikeLineBot
\ No newline at end of file + })(window)
分類 - Line API
2023
(技術)製作自動排程的YoubikeLineBot
(技術)製作自動排程的YoubikeLineBot
\ No newline at end of file diff --git a/categories/Linux/index.html b/categories/Linux/index.html index dde025ee..64625005 100644 --- a/categories/Linux/index.html +++ b/categories/Linux/index.html @@ -38,7 +38,7 @@ toc: true, rightside: false, } -}
分類 - Linux
2023
(心得)我的第一台Lubuntu筆電
(心得)我的第一台Lubuntu筆電
\ No newline at end of file + })(window)
分類 - Linux
2023
(心得)我的第一台Lubuntu筆電
(心得)我的第一台Lubuntu筆電
\ No newline at end of file diff --git a/categories/index.html b/categories/index.html index 845f0410..145c0cbf 100644 --- a/categories/index.html +++ b/categories/index.html @@ -123,7 +123,7 @@ } } detectApple() - })(window)
\ No newline at end of file +}
\ No newline at end of file diff --git a/css/index.css b/css/index.css index 21786177..24b020ec 100644 --- a/css/index.css +++ b/css/index.css @@ -1,3 +1,3 @@ -/* build time:Sun Nov 19 2023 19:47:10 GMT+0800 (台北標準時間)*/ +/* build time:Sun Dec 10 2023 14:50:17 GMT+0800 (台北標準時間)*/ /*! normalize.css v8.0.1 | MIT License | github.com/necolas/normalize.css */html{line-height:1.15;-webkit-text-size-adjust:100%}body{margin:0}main{display:block}h1{font-size:2em;margin:.67em 0}hr{box-sizing:content-box;height:0;overflow:visible}pre{font-family:monospace,monospace;font-size:1em}a{background-color:transparent}abbr[title]{border-bottom:none;text-decoration:underline;text-decoration:underline dotted}b,strong{font-weight:bolder}code,kbd,samp{font-family:monospace,monospace;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}img{border-style:none}button,input,optgroup,select,textarea{font-family:inherit;font-size:100%;line-height:1.15;margin:0}button,input{overflow:visible}button,select{text-transform:none}[type=button],[type=reset],[type=submit],button{-webkit-appearance:button}[type=button]::-moz-focus-inner,[type=reset]::-moz-focus-inner,[type=submit]::-moz-focus-inner,button::-moz-focus-inner{border-style:none;padding:0}[type=button]:-moz-focusring,[type=reset]:-moz-focusring,[type=submit]:-moz-focusring,button:-moz-focusring{outline:1px dotted ButtonText}fieldset{padding:.35em .75em .625em}legend{box-sizing:border-box;color:inherit;display:table;max-width:100%;padding:0;white-space:normal}progress{vertical-align:baseline}textarea{overflow:auto}[type=checkbox],[type=radio]{box-sizing:border-box;padding:0}[type=number]::-webkit-inner-spin-button,[type=number]::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}[type=search]::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}details{display:block}summary{display:list-item}template{display:none}[hidden]{display:none}#article-container .flink .flink-item-desc,#article-container .flink .flink-item-name,#aside-content .card-archives ul.card-archive-list>.card-archive-list-item a span,#aside-content .card-categories ul.card-category-list>.card-category-list-item a span,#nav #blog-info,#pagination .next_info,#pagination .prev_info,#sidebar #sidebar-menus .menus_items .site-page,.limit-one-line,.site-data>a .headline{overflow:hidden;-o-text-overflow:ellipsis;text-overflow:ellipsis;white-space:nowrap}#article-container figure.gallery-group .gallery-group-name,#article-container figure.gallery-group p,#aside-content .aside-list>.aside-list-item .content>.comment,#aside-content .aside-list>.aside-list-item .content>.name,#aside-content .aside-list>.aside-list-item .content>.title,#post-info .post-title,#recent-posts>.recent-post-item>.recent-post-info>.article-title,#recent-posts>.recent-post-item>.recent-post-info>.content,.article-sort-item-title,.limit-more-line,.relatedPosts>.relatedPosts-list .content .title{display:-webkit-box;overflow:hidden;-webkit-box-orient:vertical}#article-container h1:before,#article-container h2:before,#article-container h3:before,#article-container h4:before,#article-container h5:before,#article-container h6:before,#post .post-copyright:before,#post .post-outdate-notice:before,.fontawesomeIcon,.note:not(.no-icon)::before,hr:before{display:inline-block;font-weight:600;font-family:'Font Awesome 6 Free';text-rendering:auto;-webkit-font-smoothing:antialiased}#aside-content .card-widget,#recent-posts>.recent-post-item,.cardHover,.layout>.recent-posts .pagination>:not(.space),.layout>div:first-child:not(.recent-posts){border-radius:8px;background:var(--card-bg);-webkit-box-shadow:var(--card-box-shadow);box-shadow:var(--card-box-shadow);-webkit-transition:all .3s;-moz-transition:all .3s;-o-transition:all .3s;-ms-transition:all .3s;transition:all .3s}#aside-content .card-widget:hover,#recent-posts>.recent-post-item:hover,.cardHover:hover,.layout>.recent-posts .pagination>:not(.space):hover,.layout>div:first-child:not(.recent-posts):hover{-webkit-box-shadow:var(--card-hover-box-shadow);box-shadow:var(--card-hover-box-shadow)}#aside-content .aside-list>.aside-list-item .thumbnail :first-child,#recent-posts>.recent-post-item .post_cover .post-bg,.article-sort-item-img :first-child,.imgHover{width:100%;height:100%;-webkit-transition:filter 375ms ease-in .2s,-webkit-transform .6s;-moz-transition:filter 375ms ease-in .2s,-moz-transform .6s;-o-transition:filter 375ms ease-in .2s,-o-transform .6s;-ms-transition:filter 375ms ease-in .2s,-ms-transform .6s;transition:filter 375ms ease-in .2s,transform .6s;object-fit:cover}#aside-content .aside-list>.aside-list-item .thumbnail :first-child:hover,#recent-posts>.recent-post-item .post_cover .post-bg:hover,.article-sort-item-img :first-child:hover,.imgHover:hover{-webkit-transform:scale(1.1);-moz-transform:scale(1.1);-o-transform:scale(1.1);-ms-transform:scale(1.1);transform:scale(1.1)}#pagination .next-post:hover .cover,#pagination .prev-post:hover .cover,.postImgHover:hover .cover,.relatedPosts>.relatedPosts-list>div:hover .cover{opacity:.8;-webkit-transform:scale(1.1);-moz-transform:scale(1.1);-o-transform:scale(1.1);-ms-transform:scale(1.1);transform:scale(1.1)}#pagination .next-post .cover,#pagination .prev-post .cover,.postImgHover .cover,.relatedPosts>.relatedPosts-list>div .cover{position:absolute;width:100%;height:100%;opacity:.4;-webkit-transition:all .6s,filter 375ms ease-in .2s;-moz-transition:all .6s,filter 375ms ease-in .2s;-o-transition:all .6s,filter 375ms ease-in .2s;-ms-transition:all .6s,filter 375ms ease-in .2s;transition:all .6s,filter 375ms ease-in .2s;object-fit:cover}.category-lists ul,.list-beauty{list-style:none}.category-lists ul li,.list-beauty li{position:relative;padding:.12em .4em .12em 1.4em}.category-lists ul li:hover:before,.list-beauty li:hover:before{border-color:var(--pseudo-hover)}.category-lists ul li:before,.list-beauty li:before{position:absolute;top:.67em;left:0;width:.43em;height:.43em;border:.215em solid #49b1f5;border-radius:.43em;background:0 0;content:'';cursor:pointer;-webkit-transition:all .3s ease-out;-moz-transition:all .3s ease-out;-o-transition:all .3s ease-out;-ms-transition:all .3s ease-out;transition:all .3s ease-out}#content-inner,#footer{-webkit-animation:bottom-top 1s;-moz-animation:bottom-top 1s;-o-animation:bottom-top 1s;-ms-animation:bottom-top 1s;animation:bottom-top 1s}#page-header{-webkit-animation:header-effect 1s;-moz-animation:header-effect 1s;-o-animation:header-effect 1s;-ms-animation:header-effect 1s;animation:header-effect 1s}#site-subtitle,#site-title{-webkit-animation:titleScale 1s;-moz-animation:titleScale 1s;-o-animation:titleScale 1s;-ms-animation:titleScale 1s;animation:titleScale 1s}#nav.show{-webkit-animation:headerNoOpacity 1s;-moz-animation:headerNoOpacity 1s;-o-animation:headerNoOpacity 1s;-ms-animation:headerNoOpacity 1s;animation:headerNoOpacity 1s}#web_bg,canvas:not(#ribbon-canvas){-webkit-animation:to_show 4s;-moz-animation:to_show 4s;-o-animation:to_show 4s;-ms-animation:to_show 4s;animation:to_show 4s}#ribbon-canvas{-webkit-animation:ribbon_to_show 4s;-moz-animation:ribbon_to_show 4s;-o-animation:ribbon_to_show 4s;-ms-animation:ribbon_to_show 4s;animation:ribbon_to_show 4s}#sidebar-menus.open>:nth-child(1){-webkit-animation:sidebarItem .2s;-moz-animation:sidebarItem .2s;-o-animation:sidebarItem .2s;-ms-animation:sidebarItem .2s;animation:sidebarItem .2s}#sidebar-menus.open>:nth-child(2){-webkit-animation:sidebarItem .4s;-moz-animation:sidebarItem .4s;-o-animation:sidebarItem .4s;-ms-animation:sidebarItem .4s;animation:sidebarItem .4s}#sidebar-menus.open>:nth-child(3){-webkit-animation:sidebarItem .6s;-moz-animation:sidebarItem .6s;-o-animation:sidebarItem .6s;-ms-animation:sidebarItem .6s;animation:sidebarItem .6s}#sidebar-menus.open>:nth-child(4){-webkit-animation:sidebarItem .8s;-moz-animation:sidebarItem .8s;-o-animation:sidebarItem .8s;-ms-animation:sidebarItem .8s;animation:sidebarItem .8s}.scroll-down-effects{-webkit-animation:scroll-down-effect 1.5s infinite;-moz-animation:scroll-down-effect 1.5s infinite;-o-animation:scroll-down-effect 1.5s infinite;-ms-animation:scroll-down-effect 1.5s infinite;animation:scroll-down-effect 1.5s infinite}.reward-main{-webkit-animation:donate_effcet .3s .1s ease both;-moz-animation:donate_effcet .3s .1s ease both;-o-animation:donate_effcet .3s .1s ease both;-ms-animation:donate_effcet .3s .1s ease both;animation:donate_effcet .3s .1s ease both}@-moz-keyframes scroll-down-effect{0%{top:0;opacity:.4}50%{top:-16px;opacity:1;-ms-filter:none;filter:none}100%{top:0;opacity:.4}}@-webkit-keyframes scroll-down-effect{0%{top:0;opacity:.4}50%{top:-16px;opacity:1;-ms-filter:none;filter:none}100%{top:0;opacity:.4}}@-o-keyframes scroll-down-effect{0%{top:0;opacity:.4}50%{top:-16px;opacity:1;-ms-filter:none;filter:none}100%{top:0;opacity:.4}}@keyframes scroll-down-effect{0%{top:0;opacity:.4}50%{top:-16px;opacity:1;-ms-filter:none;filter:none}100%{top:0;opacity:.4}}@-moz-keyframes header-effect{0%{opacity:0;-webkit-transform:translateY(-50px);-moz-transform:translateY(-50px);-o-transform:translateY(-50px);-ms-transform:translateY(-50px);transform:translateY(-50px)}100%{opacity:1;-ms-filter:none;filter:none;-webkit-transform:translateY(0);-moz-transform:translateY(0);-o-transform:translateY(0);-ms-transform:translateY(0);transform:translateY(0)}}@-webkit-keyframes header-effect{0%{opacity:0;-webkit-transform:translateY(-50px);-moz-transform:translateY(-50px);-o-transform:translateY(-50px);-ms-transform:translateY(-50px);transform:translateY(-50px)}100%{opacity:1;-ms-filter:none;filter:none;-webkit-transform:translateY(0);-moz-transform:translateY(0);-o-transform:translateY(0);-ms-transform:translateY(0);transform:translateY(0)}}@-o-keyframes header-effect{0%{opacity:0;-webkit-transform:translateY(-50px);-moz-transform:translateY(-50px);-o-transform:translateY(-50px);-ms-transform:translateY(-50px);transform:translateY(-50px)}100%{opacity:1;-ms-filter:none;filter:none;-webkit-transform:translateY(0);-moz-transform:translateY(0);-o-transform:translateY(0);-ms-transform:translateY(0);transform:translateY(0)}}@keyframes header-effect{0%{opacity:0;-webkit-transform:translateY(-50px);-moz-transform:translateY(-50px);-o-transform:translateY(-50px);-ms-transform:translateY(-50px);transform:translateY(-50px)}100%{opacity:1;-ms-filter:none;filter:none;-webkit-transform:translateY(0);-moz-transform:translateY(0);-o-transform:translateY(0);-ms-transform:translateY(0);transform:translateY(0)}}@-moz-keyframes headerNoOpacity{0%{-webkit-transform:translateY(-50px);-moz-transform:translateY(-50px);-o-transform:translateY(-50px);-ms-transform:translateY(-50px);transform:translateY(-50px)}100%{-webkit-transform:translateY(0);-moz-transform:translateY(0);-o-transform:translateY(0);-ms-transform:translateY(0);transform:translateY(0)}}@-webkit-keyframes headerNoOpacity{0%{-webkit-transform:translateY(-50px);-moz-transform:translateY(-50px);-o-transform:translateY(-50px);-ms-transform:translateY(-50px);transform:translateY(-50px)}100%{-webkit-transform:translateY(0);-moz-transform:translateY(0);-o-transform:translateY(0);-ms-transform:translateY(0);transform:translateY(0)}}@-o-keyframes headerNoOpacity{0%{-webkit-transform:translateY(-50px);-moz-transform:translateY(-50px);-o-transform:translateY(-50px);-ms-transform:translateY(-50px);transform:translateY(-50px)}100%{-webkit-transform:translateY(0);-moz-transform:translateY(0);-o-transform:translateY(0);-ms-transform:translateY(0);transform:translateY(0)}}@keyframes headerNoOpacity{0%{-webkit-transform:translateY(-50px);-moz-transform:translateY(-50px);-o-transform:translateY(-50px);-ms-transform:translateY(-50px);transform:translateY(-50px)}100%{-webkit-transform:translateY(0);-moz-transform:translateY(0);-o-transform:translateY(0);-ms-transform:translateY(0);transform:translateY(0)}}@-moz-keyframes bottom-top{0%{margin-top:50px;opacity:0}100%{margin-top:0;opacity:1;-ms-filter:none;filter:none}}@-webkit-keyframes bottom-top{0%{margin-top:50px;opacity:0}100%{margin-top:0;opacity:1;-ms-filter:none;filter:none}}@-o-keyframes bottom-top{0%{margin-top:50px;opacity:0}100%{margin-top:0;opacity:1;-ms-filter:none;filter:none}}@keyframes bottom-top{0%{margin-top:50px;opacity:0}100%{margin-top:0;opacity:1;-ms-filter:none;filter:none}}@-moz-keyframes titleScale{0%{opacity:0;-webkit-transform:scale(.7);-moz-transform:scale(.7);-o-transform:scale(.7);-ms-transform:scale(.7);transform:scale(.7)}100%{opacity:1;-ms-filter:none;filter:none;-webkit-transform:scale(1);-moz-transform:scale(1);-o-transform:scale(1);-ms-transform:scale(1);transform:scale(1)}}@-webkit-keyframes titleScale{0%{opacity:0;-webkit-transform:scale(.7);-moz-transform:scale(.7);-o-transform:scale(.7);-ms-transform:scale(.7);transform:scale(.7)}100%{opacity:1;-ms-filter:none;filter:none;-webkit-transform:scale(1);-moz-transform:scale(1);-o-transform:scale(1);-ms-transform:scale(1);transform:scale(1)}}@-o-keyframes titleScale{0%{opacity:0;-webkit-transform:scale(.7);-moz-transform:scale(.7);-o-transform:scale(.7);-ms-transform:scale(.7);transform:scale(.7)}100%{opacity:1;-ms-filter:none;filter:none;-webkit-transform:scale(1);-moz-transform:scale(1);-o-transform:scale(1);-ms-transform:scale(1);transform:scale(1)}}@keyframes titleScale{0%{opacity:0;-webkit-transform:scale(.7);-moz-transform:scale(.7);-o-transform:scale(.7);-ms-transform:scale(.7);transform:scale(.7)}100%{opacity:1;-ms-filter:none;filter:none;-webkit-transform:scale(1);-moz-transform:scale(1);-o-transform:scale(1);-ms-transform:scale(1);transform:scale(1)}}@-moz-keyframes search_close{0%{opacity:1;-ms-filter:none;filter:none;-webkit-transform:scale(1);-moz-transform:scale(1);-o-transform:scale(1);-ms-transform:scale(1);transform:scale(1)}100%{opacity:0;-webkit-transform:scale(.7);-moz-transform:scale(.7);-o-transform:scale(.7);-ms-transform:scale(.7);transform:scale(.7)}}@-webkit-keyframes search_close{0%{opacity:1;-ms-filter:none;filter:none;-webkit-transform:scale(1);-moz-transform:scale(1);-o-transform:scale(1);-ms-transform:scale(1);transform:scale(1)}100%{opacity:0;-webkit-transform:scale(.7);-moz-transform:scale(.7);-o-transform:scale(.7);-ms-transform:scale(.7);transform:scale(.7)}}@-o-keyframes search_close{0%{opacity:1;-ms-filter:none;filter:none;-webkit-transform:scale(1);-moz-transform:scale(1);-o-transform:scale(1);-ms-transform:scale(1);transform:scale(1)}100%{opacity:0;-webkit-transform:scale(.7);-moz-transform:scale(.7);-o-transform:scale(.7);-ms-transform:scale(.7);transform:scale(.7)}}@keyframes search_close{0%{opacity:1;-ms-filter:none;filter:none;-webkit-transform:scale(1);-moz-transform:scale(1);-o-transform:scale(1);-ms-transform:scale(1);transform:scale(1)}100%{opacity:0;-webkit-transform:scale(.7);-moz-transform:scale(.7);-o-transform:scale(.7);-ms-transform:scale(.7);transform:scale(.7)}}@-moz-keyframes to_show{0%{opacity:0}100%{opacity:1;-ms-filter:none;filter:none}}@-webkit-keyframes to_show{0%{opacity:0}100%{opacity:1;-ms-filter:none;filter:none}}@-o-keyframes to_show{0%{opacity:0}100%{opacity:1;-ms-filter:none;filter:none}}@keyframes to_show{0%{opacity:0}100%{opacity:1;-ms-filter:none;filter:none}}@-moz-keyframes to_hide{0%{opacity:1;-ms-filter:none;filter:none}100%{opacity:0}}@-webkit-keyframes to_hide{0%{opacity:1;-ms-filter:none;filter:none}100%{opacity:0}}@-o-keyframes to_hide{0%{opacity:1;-ms-filter:none;filter:none}100%{opacity:0}}@keyframes to_hide{0%{opacity:1;-ms-filter:none;filter:none}100%{opacity:0}}@-moz-keyframes ribbon_to_show{0%{opacity:0}100%{opacity:.6}}@-webkit-keyframes ribbon_to_show{0%{opacity:0}100%{opacity:.6}}@-o-keyframes ribbon_to_show{0%{opacity:0}100%{opacity:.6}}@keyframes ribbon_to_show{0%{opacity:0}100%{opacity:.6}}@-moz-keyframes avatar_turn_around{from{-webkit-transform:rotate(0);-moz-transform:rotate(0);-o-transform:rotate(0);-ms-transform:rotate(0);transform:rotate(0)}to{-webkit-transform:rotate(360deg);-moz-transform:rotate(360deg);-o-transform:rotate(360deg);-ms-transform:rotate(360deg);transform:rotate(360deg)}}@-webkit-keyframes avatar_turn_around{from{-webkit-transform:rotate(0);-moz-transform:rotate(0);-o-transform:rotate(0);-ms-transform:rotate(0);transform:rotate(0)}to{-webkit-transform:rotate(360deg);-moz-transform:rotate(360deg);-o-transform:rotate(360deg);-ms-transform:rotate(360deg);transform:rotate(360deg)}}@-o-keyframes avatar_turn_around{from{-webkit-transform:rotate(0);-moz-transform:rotate(0);-o-transform:rotate(0);-ms-transform:rotate(0);transform:rotate(0)}to{-webkit-transform:rotate(360deg);-moz-transform:rotate(360deg);-o-transform:rotate(360deg);-ms-transform:rotate(360deg);transform:rotate(360deg)}}@keyframes avatar_turn_around{from{-webkit-transform:rotate(0);-moz-transform:rotate(0);-o-transform:rotate(0);-ms-transform:rotate(0);transform:rotate(0)}to{-webkit-transform:rotate(360deg);-moz-transform:rotate(360deg);-o-transform:rotate(360deg);-ms-transform:rotate(360deg);transform:rotate(360deg)}}@-moz-keyframes sub_menus{0%{opacity:0;-webkit-transform:translateY(10px);-moz-transform:translateY(10px);-o-transform:translateY(10px);-ms-transform:translateY(10px);transform:translateY(10px)}100%{opacity:1;-ms-filter:none;filter:none;-webkit-transform:translateY(0);-moz-transform:translateY(0);-o-transform:translateY(0);-ms-transform:translateY(0);transform:translateY(0)}}@-webkit-keyframes sub_menus{0%{opacity:0;-webkit-transform:translateY(10px);-moz-transform:translateY(10px);-o-transform:translateY(10px);-ms-transform:translateY(10px);transform:translateY(10px)}100%{opacity:1;-ms-filter:none;filter:none;-webkit-transform:translateY(0);-moz-transform:translateY(0);-o-transform:translateY(0);-ms-transform:translateY(0);transform:translateY(0)}}@-o-keyframes sub_menus{0%{opacity:0;-webkit-transform:translateY(10px);-moz-transform:translateY(10px);-o-transform:translateY(10px);-ms-transform:translateY(10px);transform:translateY(10px)}100%{opacity:1;-ms-filter:none;filter:none;-webkit-transform:translateY(0);-moz-transform:translateY(0);-o-transform:translateY(0);-ms-transform:translateY(0);transform:translateY(0)}}@keyframes sub_menus{0%{opacity:0;-webkit-transform:translateY(10px);-moz-transform:translateY(10px);-o-transform:translateY(10px);-ms-transform:translateY(10px);transform:translateY(10px)}100%{opacity:1;-ms-filter:none;filter:none;-webkit-transform:translateY(0);-moz-transform:translateY(0);-o-transform:translateY(0);-ms-transform:translateY(0);transform:translateY(0)}}@-moz-keyframes donate_effcet{0%{opacity:0;-webkit-transform:translateY(-20px);-moz-transform:translateY(-20px);-o-transform:translateY(-20px);-ms-transform:translateY(-20px);transform:translateY(-20px)}100%{opacity:1;-ms-filter:none;filter:none;-webkit-transform:translateY(0);-moz-transform:translateY(0);-o-transform:translateY(0);-ms-transform:translateY(0);transform:translateY(0)}}@-webkit-keyframes donate_effcet{0%{opacity:0;-webkit-transform:translateY(-20px);-moz-transform:translateY(-20px);-o-transform:translateY(-20px);-ms-transform:translateY(-20px);transform:translateY(-20px)}100%{opacity:1;-ms-filter:none;filter:none;-webkit-transform:translateY(0);-moz-transform:translateY(0);-o-transform:translateY(0);-ms-transform:translateY(0);transform:translateY(0)}}@-o-keyframes donate_effcet{0%{opacity:0;-webkit-transform:translateY(-20px);-moz-transform:translateY(-20px);-o-transform:translateY(-20px);-ms-transform:translateY(-20px);transform:translateY(-20px)}100%{opacity:1;-ms-filter:none;filter:none;-webkit-transform:translateY(0);-moz-transform:translateY(0);-o-transform:translateY(0);-ms-transform:translateY(0);transform:translateY(0)}}@keyframes donate_effcet{0%{opacity:0;-webkit-transform:translateY(-20px);-moz-transform:translateY(-20px);-o-transform:translateY(-20px);-ms-transform:translateY(-20px);transform:translateY(-20px)}100%{opacity:1;-ms-filter:none;filter:none;-webkit-transform:translateY(0);-moz-transform:translateY(0);-o-transform:translateY(0);-ms-transform:translateY(0);transform:translateY(0)}}@-moz-keyframes sidebarItem{0%{-webkit-transform:translateX(200px);-moz-transform:translateX(200px);-o-transform:translateX(200px);-ms-transform:translateX(200px);transform:translateX(200px)}100%{-webkit-transform:translateX(0);-moz-transform:translateX(0);-o-transform:translateX(0);-ms-transform:translateX(0);transform:translateX(0)}}@-webkit-keyframes sidebarItem{0%{-webkit-transform:translateX(200px);-moz-transform:translateX(200px);-o-transform:translateX(200px);-ms-transform:translateX(200px);transform:translateX(200px)}100%{-webkit-transform:translateX(0);-moz-transform:translateX(0);-o-transform:translateX(0);-ms-transform:translateX(0);transform:translateX(0)}}@-o-keyframes sidebarItem{0%{-webkit-transform:translateX(200px);-moz-transform:translateX(200px);-o-transform:translateX(200px);-ms-transform:translateX(200px);transform:translateX(200px)}100%{-webkit-transform:translateX(0);-moz-transform:translateX(0);-o-transform:translateX(0);-ms-transform:translateX(0);transform:translateX(0)}}@keyframes sidebarItem{0%{-webkit-transform:translateX(200px);-moz-transform:translateX(200px);-o-transform:translateX(200px);-ms-transform:translateX(200px);transform:translateX(200px)}100%{-webkit-transform:translateX(0);-moz-transform:translateX(0);-o-transform:translateX(0);-ms-transform:translateX(0);transform:translateX(0)}}:root{--global-font-size:14px;--global-bg:#fff;--font-color:#4c4948;--hr-border:#a4d8fa;--hr-before-color:#80c8f8;--search-bg:#f6f8fa;--search-input-color:#4c4948;--search-result-title:#4c4948;--preloader-bg:#37474f;--preloader-color:#fff;--tab-border-color:#f0f0f0;--tab-botton-bg:#f0f0f0;--tab-botton-color:#1f2d3d;--tab-button-hover-bg:#dcdcdc;--tab-button-active-bg:#fff;--card-bg:#fff;--sidebar-bg:#f6f8fa;--btn-hover-color:#ff7242;--btn-color:#fff;--btn-bg:#49b1f5;--text-bg-hover:rgba(73,177,245,0.7);--light-grey:#eee;--dark-grey:#cacaca;--white:#fff;--text-highlight-color:#1f2d3d;--blockquote-color:#6a737d;--blockquote-bg:rgba(73,177,245,0.1);--reward-pop:#f5f5f5;--toc-link-color:#666261;--card-box-shadow:0 3px 8px 6px rgba(7,17,27,0.05);--card-hover-box-shadow:0 3px 8px 6px rgba(7,17,27,0.09);--pseudo-hover:#ff7242;--headline-presudo:#a0a0a0;--scrollbar-color:#49b1f5;--default-bg-color:#49b1f5}body{position:relative;min-height:100%;background:var(--global-bg);color:var(--font-color);font-size:var(--global-font-size);font-family:-apple-system,BlinkMacSystemFont,'Segoe UI','Helvetica Neue',Lato,Roboto,'PingFang SC','Microsoft YaHei',sans-serif;line-height:2;-webkit-tap-highlight-color:transparent}::-webkit-scrollbar{width:8px;height:8px}::-webkit-scrollbar-thumb{background:var(--scrollbar-color)}::-webkit-scrollbar-track{background-color:transparent}*{scrollbar-width:thin;scrollbar-color:var(--scrollbar-color) transparent}input::placeholder{color:var(--font-color)}h1,h2,h3,h4,h5,h6{position:relative;margin:20px 0 14px;color:var(--text-highlight-color);font-weight:700}h1 code,h2 code,h3 code,h4 code,h5 code,h6 code{font-size:inherit!important}*{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}hr{position:relative;margin:40px auto;border:2px dashed var(--hr-border);width:calc(100% - 4px)}hr:hover:before{left:calc(95% - 20px)}hr:before{position:absolute;top:-10px;left:5%;z-index:1;color:var(--hr-before-color);content:'\f0c4';font-size:20px;line-height:1;-webkit-transition:all 1s ease-in-out;-moz-transition:all 1s ease-in-out;-o-transition:all 1s ease-in-out;-ms-transition:all 1s ease-in-out;transition:all 1s ease-in-out}.table-wrap{overflow-x:scroll;margin:0 0 20px}table{display:table;width:100%;border-spacing:0;border-collapse:collapse;empty-cells:show}table thead{background:rgba(153,169,191,.1)}table td,table th{padding:6px 12px;border:1px solid var(--light-grey);vertical-align:middle}::selection{background:#00c4b6;color:#f7f7f7}button{padding:0;outline:0;border:none;background:0 0;cursor:pointer;touch-action:manipulation}a{color:#99a9bf;text-decoration:none;word-wrap:break-word;-webkit-transition:all .2s;-moz-transition:all .2s;-o-transition:all .2s;-ms-transition:all .2s;transition:all .2s;overflow-wrap:break-word}a:hover{color:#49b1f5}.is-center{text-align:center}.copy-true{-webkit-user-select:all;-moz-user-select:all;-ms-user-select:all;user-select:all}.pull-left{float:left}.pull-right{float:right}img:not([src]),img[src='']{opacity:0}.img-alt{margin:-10px 0 10px;color:#858585}.img-alt:hover{text-decoration:none!important}blockquote{margin:0 0 20px;padding:12px 15px;border-left:3px solid #49b1f5;background-color:var(--blockquote-bg);color:var(--blockquote-color)}blockquote footer cite:before{padding:0 5px;content:'—'}blockquote>:last-child{margin-bottom:0!important}:root{--hl-color:#eff;--hl-bg:#212121;--hltools-bg:#1c1c1c;--hltools-color:rgba(238,255,255,0.8);--hlnumber-bg:#212121;--hlnumber-color:rgba(238,255,255,0.5);--hlscrollbar-bg:#353535;--hlexpand-bg:linear-gradient(180deg, rgba(33,33,33,0.6), rgba(33,33,33,0.9))}figure.highlight table{scrollbar-color:var(--hlscrollbar-bg) transparent}figure.highlight table::-webkit-scrollbar-thumb{background:var(--hlscrollbar-bg)}figure.highlight pre .deletion{color:#bf42bf}figure.highlight pre .addition{color:#105ede}figure.highlight pre .meta{color:#c792ea}figure.highlight pre .comment{color:#969896}figure.highlight pre .attribute,figure.highlight pre .css .class,figure.highlight pre .css .id,figure.highlight pre .css .pseudo,figure.highlight pre .html .doctype,figure.highlight pre .regexp,figure.highlight pre .ruby .constant,figure.highlight pre .tag .name,figure.highlight pre .variable,figure.highlight pre .xml .doctype,figure.highlight pre .xml .pi,figure.highlight pre .xml .tag .title{color:#ff5370}figure.highlight pre .tag{color:#89ddff}figure.highlight pre .command,figure.highlight pre .constant,figure.highlight pre .literal,figure.highlight pre .number,figure.highlight pre .params,figure.highlight pre .preprocessor{color:#f78c6c}figure.highlight pre .built_in{color:#ffcb6b}figure.highlight pre .css .rules .attribute,figure.highlight pre .formula,figure.highlight pre .header,figure.highlight pre .inheritance,figure.highlight pre .number,figure.highlight pre .ruby .class .title,figure.highlight pre .ruby .symbol,figure.highlight pre .special,figure.highlight pre .string,figure.highlight pre .value,figure.highlight pre .xml .cdata{color:#c3e88d}figure.highlight pre .css .hexcolor,figure.highlight pre .keyword,figure.highlight pre .title{color:#89ddff}figure.highlight pre .coffeescript .title,figure.highlight pre .function,figure.highlight pre .javascript .title,figure.highlight pre .perl .sub,figure.highlight pre .python .decorator,figure.highlight pre .python .title,figure.highlight pre .ruby .function .title,figure.highlight pre .ruby .title .keyword{color:#82aaff}figure.highlight pre .javascript .function,figure.highlight pre .tag .attr{color:#c792ea}#article-container figure.highlight .line.marked{background-color:rgba(97,97,97,.314)}#article-container figure.highlight table{display:block;overflow:auto;border:none}#article-container figure.highlight table td{padding:0;border:none}#article-container figure.highlight .gutter pre{padding-right:10px;padding-left:10px;background-color:var(--hlnumber-bg);color:var(--hlnumber-color);text-align:right}#article-container figure.highlight .code pre{padding-right:10px;padding-left:10px;width:100%}#article-container figure.highlight,#article-container pre{overflow:auto;margin:0 0 20px;padding:0;background:var(--hl-bg);color:var(--hl-color);line-height:1.6}#article-container code,#article-container pre{font-size:var(--global-font-size);font-family:consolas,Menlo,'PingFang SC','Microsoft YaHei',sans-serif!important}#article-container code{padding:2px 4px;background:rgba(27,31,35,.05);color:#f47466}#article-container pre{padding:10px 20px}#article-container pre code{padding:0;background:0 0;color:var(--hl-color);text-shadow:none}#article-container figure.highlight{position:relative}#article-container figure.highlight pre{margin:0;padding:8px 0;border:none}#article-container figure.highlight .caption,#article-container figure.highlight figcaption{padding:6px 0 2px 14px;font-size:var(--global-font-size);line-height:1em}#article-container figure.highlight .caption a,#article-container figure.highlight figcaption a{float:right;padding-right:10px;color:var(--hl-color)}#article-container figure.highlight .caption a:hover,#article-container figure.highlight figcaption a:hover{border-bottom-color:var(--hl-color)}#article-container .highlight-tools{position:relative;display:-webkit-box;display:-moz-box;display:-webkit-flex;display:-ms-flexbox;display:box;display:flex;-webkit-box-align:center;-moz-box-align:center;-o-box-align:center;-ms-flex-align:center;-webkit-align-items:center;align-items:center;overflow:hidden;min-height:24px;height:2.15em;background:var(--hltools-bg);color:var(--hltools-color);font-size:var(--global-font-size)}#article-container .highlight-tools.closed~*{display:none}#article-container .highlight-tools .expand{position:absolute;padding:.57em .7em;cursor:pointer;-webkit-transition:-webkit-transform .3s;-moz-transition:-moz-transform .3s;-o-transition:-o-transform .3s;-ms-transition:-ms-transform .3s;transition:transform .3s}#article-container .highlight-tools .expand+.code-lang{left:1.7em}#article-container .highlight-tools .expand.closed{-webkit-transition:all .3s;-moz-transition:all .3s;-o-transition:all .3s;-ms-transition:all .3s;transition:all .3s;-webkit-transform:rotate(-90deg)!important;-moz-transform:rotate(-90deg)!important;-o-transform:rotate(-90deg)!important;-ms-transform:rotate(-90deg)!important;transform:rotate(-90deg)!important}#article-container .highlight-tools .code-lang{position:absolute;left:14px;text-transform:uppercase;font-weight:700;font-size:1.15em;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}#article-container .highlight-tools .copy-notice{position:absolute;right:2.4em;opacity:0;-webkit-transition:opacity .4s;-moz-transition:opacity .4s;-o-transition:opacity .4s;-ms-transition:opacity .4s;transition:opacity .4s}#article-container .highlight-tools .copy-button{position:absolute;right:14px;cursor:pointer;-webkit-transition:color .2s;-moz-transition:color .2s;-o-transition:color .2s;-ms-transition:color .2s;transition:color .2s}#article-container .highlight-tools .copy-button:hover{color:#49b1f5}#article-container .gutter{-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}#article-container .gist table{width:auto}#article-container .gist table td{border:none}@-moz-keyframes code-expand-key{0%{opacity:.6}50%{opacity:.1}100%{opacity:.6}}@-webkit-keyframes code-expand-key{0%{opacity:.6}50%{opacity:.1}100%{opacity:.6}}@-o-keyframes code-expand-key{0%{opacity:.6}50%{opacity:.1}100%{opacity:.6}}@keyframes code-expand-key{0%{opacity:.6}50%{opacity:.1}100%{opacity:.6}}.article-sort{margin-left:10px;padding-left:20px;border-left:2px solid #aadafa}.article-sort-title{position:relative;margin-left:10px;padding-bottom:20px;padding-left:20px;font-size:1.72em}.article-sort-title:hover:before{border-color:var(--pseudo-hover)}.article-sort-title:before{position:absolute;top:calc(((100% - 36px)/ 2));left:-9px;z-index:1;width:10px;height:10px;border:5px solid #49b1f5;border-radius:10px;background:var(--card-bg);content:'';line-height:10px;-webkit-transition:all .2s ease-in-out;-moz-transition:all .2s ease-in-out;-o-transition:all .2s ease-in-out;-ms-transition:all .2s ease-in-out;transition:all .2s ease-in-out}.article-sort-title:after{position:absolute;bottom:0;left:0;z-index:0;width:2px;height:1.5em;background:#aadafa;content:''}.article-sort-item{position:relative;display:-webkit-box;display:-moz-box;display:-webkit-flex;display:-ms-flexbox;display:box;display:flex;-webkit-box-align:center;-moz-box-align:center;-o-box-align:center;-ms-flex-align:center;-webkit-align-items:center;align-items:center;margin:0 0 20px 10px;-webkit-transition:all .2s ease-in-out;-moz-transition:all .2s ease-in-out;-o-transition:all .2s ease-in-out;-ms-transition:all .2s ease-in-out;transition:all .2s ease-in-out}.article-sort-item:hover:before{border-color:var(--pseudo-hover)}.article-sort-item:before{position:absolute;left:calc(-20px - 17px);width:6px;height:6px;border:3px solid #49b1f5;border-radius:6px;background:var(--card-bg);content:'';-webkit-transition:all .2s ease-in-out;-moz-transition:all .2s ease-in-out;-o-transition:all .2s ease-in-out;-ms-transition:all .2s ease-in-out;transition:all .2s ease-in-out}.article-sort-item.no-article-cover{height:80px}.article-sort-item.no-article-cover .article-sort-item-info{padding:0}.article-sort-item.year{font-size:1.43em}.article-sort-item.year:hover:before{border-color:#49b1f5}.article-sort-item.year:before{border-color:var(--pseudo-hover)}.article-sort-item-time{color:#858585;font-size:95%}.article-sort-item-time time{padding-left:6px;cursor:default}.article-sort-item-title{color:var(--font-color);font-size:1.1em;-webkit-transition:all .3s;-moz-transition:all .3s;-o-transition:all .3s;-ms-transition:all .3s;transition:all .3s;-webkit-line-clamp:2}.article-sort-item-title:hover{color:#49b1f5;-webkit-transform:translateX(10px);-moz-transform:translateX(10px);-o-transform:translateX(10px);-ms-transform:translateX(10px);transform:translateX(10px)}.article-sort-item-img{overflow:hidden;width:80px;height:80px}.article-sort-item-info{-webkit-box-flex:1;-moz-box-flex:1;-o-box-flex:1;box-flex:1;-webkit-flex:1;-ms-flex:1;flex:1;padding:0 16px}.category-lists .category-title{font-size:2.57em}@media screen and (max-width:768px){.category-lists .category-title{font-size:2em}}.category-lists .category-list{margin-bottom:0}.category-lists .category-list a{color:var(--font-color)}.category-lists .category-list a:hover{color:#49b1f5}.category-lists .category-list .category-list-count{margin-left:8px;color:#858585}.category-lists .category-list .category-list-count:before{content:'('}.category-lists .category-list .category-list-count:after{content:')'}.category-lists ul{padding:0 0 0 20px}.category-lists ul ul{padding-left:4px}.category-lists ul li{position:relative;margin:6px 0;padding:.12em .4em .12em 1.4em}#body-wrap{display:-webkit-box;display:-moz-box;display:-webkit-flex;display:-ms-flexbox;display:box;display:flex;-webkit-box-orient:vertical;-moz-box-orient:vertical;-o-box-orient:vertical;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;min-height:100vh}.layout{display:-webkit-box;display:-moz-box;display:-webkit-flex;display:-ms-flexbox;display:box;display:flex;-webkit-box-flex:1;-moz-box-flex:1;-o-box-flex:1;box-flex:1;-webkit-flex:1 auto;-ms-flex:1 auto;flex:1 auto;margin:0 auto;padding:40px 15px;max-width:1200px;width:100%}@media screen and (max-width:900px){.layout{-webkit-box-orient:vertical;-moz-box-orient:vertical;-o-box-orient:vertical;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column}}@media screen and (max-width:768px){.layout{padding:20px 5px}}@media screen and (min-width:2000px){.layout{max-width:1500px}}.layout>div:first-child:not(.recent-posts){-webkit-align-self:flex-start;align-self:flex-start;-ms-flex-item-align:start;padding:50px 40px}@media screen and (max-width:768px){.layout>div:first-child:not(.recent-posts){padding:36px 14px}}.layout>div:first-child{width:74%;-webkit-transition:all .3s;-moz-transition:all .3s;-o-transition:all .3s;-ms-transition:all .3s;transition:all .3s}@media screen and (max-width:900px){.layout>div:first-child{width:100%!important}}.layout.hide-aside{max-width:1000px}@media screen and (min-width:2000px){.layout.hide-aside{max-width:1300px}}.layout.hide-aside>div{width:100%!important}.apple #page-header.full_page{background-attachment:scroll!important}.apple .avatar-img,.apple .flink-item-icon,.apple .recent-post-item{-webkit-transform:translateZ(0);-moz-transform:translateZ(0);-o-transform:translateZ(0);-ms-transform:translateZ(0);transform:translateZ(0)}#article-container .flink{margin-bottom:20px}#article-container .flink .flink-list{overflow:auto;padding:10px 10px 0;text-align:center}#article-container .flink .flink-list>.flink-list-item{position:relative;float:left;overflow:hidden;margin:15px 7px;width:calc(100% / 3 - 15px);height:90px;border-radius:8px;line-height:17px;-webkit-transform:translateZ(0)}@media screen and (max-width:1024px){#article-container .flink .flink-list>.flink-list-item{width:calc(50% - 15px)!important}}@media screen and (max-width:600px){#article-container .flink .flink-list>.flink-list-item{width:calc(100% - 15px)!important}}#article-container .flink .flink-list>.flink-list-item:hover .flink-item-icon{margin-left:-10px;width:0}#article-container .flink .flink-list>.flink-list-item:before{position:absolute;top:0;right:0;bottom:0;left:0;z-index:-1;background:var(--text-bg-hover);content:'';-webkit-transition:-webkit-transform .3s ease-out;-moz-transition:-moz-transform .3s ease-out;-o-transition:-o-transform .3s ease-out;-ms-transition:-ms-transform .3s ease-out;transition:transform .3s ease-out;-webkit-transform:scale(0);-moz-transform:scale(0);-o-transform:scale(0);-ms-transform:scale(0);transform:scale(0)}#article-container .flink .flink-list>.flink-list-item:active:before,#article-container .flink .flink-list>.flink-list-item:focus:before,#article-container .flink .flink-list>.flink-list-item:hover:before{-webkit-transform:scale(1);-moz-transform:scale(1);-o-transform:scale(1);-ms-transform:scale(1);transform:scale(1)}#article-container .flink .flink-list>.flink-list-item a{color:var(--font-color);text-decoration:none}#article-container .flink .flink-list>.flink-list-item a .flink-item-icon{float:left;overflow:hidden;margin:15px 10px;width:60px;height:60px;border-radius:35px;-webkit-transition:width .3s ease-out;-moz-transition:width .3s ease-out;-o-transition:width .3s ease-out;-ms-transition:width .3s ease-out;transition:width .3s ease-out}#article-container .flink .flink-list>.flink-list-item a .flink-item-icon img{width:100%;height:100%;-webkit-transition:filter 375ms ease-in .2s,-webkit-transform .3s;-moz-transition:filter 375ms ease-in .2s,-moz-transform .3s;-o-transition:filter 375ms ease-in .2s,-o-transform .3s;-ms-transition:filter 375ms ease-in .2s,-ms-transform .3s;transition:filter 375ms ease-in .2s,transform .3s;object-fit:cover}#article-container .flink .flink-list>.flink-list-item a .img-alt{display:none}#article-container .flink .flink-item-name{padding:16px 10px 0 0;height:40px;font-weight:700;font-size:1.43em}#article-container .flink .flink-item-desc{padding:16px 10px 16px 0;height:50px;font-size:.93em}#article-container .flink .flink-name{margin-bottom:5px;font-weight:700;font-size:1.5em}#recent-posts>.recent-post-item:not(:first-child){margin-top:20px}#recent-posts>.recent-post-item{display:-webkit-box;display:-moz-box;display:-webkit-flex;display:-ms-flexbox;display:box;display:flex;-webkit-box-orient:horizontal;-moz-box-orient:horizontal;-o-box-orient:horizontal;-webkit-flex-direction:row;-ms-flex-direction:row;flex-direction:row;-webkit-box-align:center;-moz-box-align:center;-o-box-align:center;-ms-flex-align:center;-webkit-align-items:center;align-items:center;overflow:hidden;height:18em}@media screen and (max-width:768px){#recent-posts>.recent-post-item{-webkit-box-orient:vertical;-moz-box-orient:vertical;-o-box-orient:vertical;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;height:auto}}#recent-posts>.recent-post-item:hover img.post-bg{-webkit-transform:scale(1.1);-moz-transform:scale(1.1);-o-transform:scale(1.1);-ms-transform:scale(1.1);transform:scale(1.1)}#recent-posts>.recent-post-item.ads-wrap{display:block!important;height:auto!important}#recent-posts>.recent-post-item .post_cover{overflow:hidden;width:44%;height:100%}@media screen and (max-width:768px){#recent-posts>.recent-post-item .post_cover{width:100%;height:230px}}#recent-posts>.recent-post-item .post_cover.right{-webkit-box-ordinal-group:1;-moz-box-ordinal-group:1;-o-box-ordinal-group:1;-ms-flex-order:1;-webkit-order:1;order:1}@media screen and (max-width:768px){#recent-posts>.recent-post-item .post_cover.right{-webkit-box-ordinal-group:0;-moz-box-ordinal-group:0;-o-box-ordinal-group:0;-ms-flex-order:0;-webkit-order:0;order:0}}#recent-posts>.recent-post-item>.recent-post-info{padding:0 40px;width:57%}@media screen and (max-width:768px){#recent-posts>.recent-post-item>.recent-post-info{padding:20px 20px 30px;width:100%}}#recent-posts>.recent-post-item>.recent-post-info.no-cover{width:100%}@media screen and (max-width:768px){#recent-posts>.recent-post-item>.recent-post-info.no-cover{padding:30px 20px}}#recent-posts>.recent-post-item>.recent-post-info>.article-title{color:var(--text-highlight-color);font-size:1.72em;line-height:1.4;-webkit-transition:all .2s ease-in-out;-moz-transition:all .2s ease-in-out;-o-transition:all .2s ease-in-out;-ms-transition:all .2s ease-in-out;transition:all .2s ease-in-out;-webkit-line-clamp:2}@media screen and (max-width:768px){#recent-posts>.recent-post-item>.recent-post-info>.article-title{font-size:1.43em}}#recent-posts>.recent-post-item>.recent-post-info>.article-title:hover{color:#49b1f5}#recent-posts>.recent-post-item>.recent-post-info>.article-meta-wrap{margin:6px 0;color:#858585;font-size:90%}#recent-posts>.recent-post-item>.recent-post-info>.article-meta-wrap>.post-meta-date{cursor:default}#recent-posts>.recent-post-item>.recent-post-info>.article-meta-wrap .sticky{color:#ff7242}#recent-posts>.recent-post-item>.recent-post-info>.article-meta-wrap i{margin:0 4px 0 0}#recent-posts>.recent-post-item>.recent-post-info>.article-meta-wrap .fa-spinner{margin:0}#recent-posts>.recent-post-item>.recent-post-info>.article-meta-wrap .article-meta-label{padding-right:4px}#recent-posts>.recent-post-item>.recent-post-info>.article-meta-wrap .article-meta-separator{margin:0 6px}#recent-posts>.recent-post-item>.recent-post-info>.article-meta-wrap .article-meta-link{margin:0 4px}#recent-posts>.recent-post-item>.recent-post-info>.article-meta-wrap a{color:#858585}#recent-posts>.recent-post-item>.recent-post-info>.article-meta-wrap a:hover{color:#49b1f5;text-decoration:underline}#recent-posts>.recent-post-item>.recent-post-info>.content{-webkit-line-clamp:2}.tag-cloud-list a{display:inline-block;padding:0 8px;-webkit-transition:all .3s;-moz-transition:all .3s;-o-transition:all .3s;-ms-transition:all .3s;transition:all .3s}.tag-cloud-list a:hover{color:#49b1f5!important;-webkit-transform:scale(1.1);-moz-transform:scale(1.1);-o-transform:scale(1.1);-ms-transform:scale(1.1);transform:scale(1.1)}@media screen and (max-width:768px){.tag-cloud-list a{zoom:.85}}.tag-cloud-title{font-size:2.57em}@media screen and (max-width:768px){.tag-cloud-title{font-size:2em}}h1.page-title+.tag-cloud-list{text-align:left}#aside-content{width:26%}@media screen and (min-width:900px){#aside-content{padding-left:15px}}@media screen and (max-width:900px){#aside-content{width:100%}}#aside-content>.card-widget:first-child{margin-top:0}@media screen and (max-width:900px){#aside-content>.card-widget:first-child{margin-top:20px}}#aside-content .card-widget{position:relative;overflow:hidden;margin-top:20px;padding:20px 24px}#aside-content .card-info .author-info__name{font-weight:500;font-size:1.57em}#aside-content .card-info .author-info__description{margin-top:-.42em}#aside-content .card-info .card-info-data{margin:14px 0 4px}#aside-content .card-info .card-info-social-icons{margin:6px 0 -6px}#aside-content .card-info .card-info-social-icons .social-icon{margin:0 10px;color:var(--font-color);font-size:1.4em}#aside-content .card-info .card-info-social-icons i{-webkit-transition:all .3s;-moz-transition:all .3s;-o-transition:all .3s;-ms-transition:all .3s;transition:all .3s}#aside-content .card-info .card-info-social-icons i:hover{-webkit-transform:rotate(540deg);-moz-transform:rotate(540deg);-o-transform:rotate(540deg);-ms-transform:rotate(540deg);transform:rotate(540deg)}#aside-content .card-info #card-info-btn{display:block;margin-top:14px;background-color:var(--btn-bg);color:var(--btn-color);text-align:center;line-height:2.4}#aside-content .card-info #card-info-btn:hover{background-color:var(--btn-hover-color)}#aside-content .card-info #card-info-btn span{padding-left:10px}#aside-content .item-headline{padding-bottom:6px;font-size:1.2em}#aside-content .item-headline span{margin-left:6px}@media screen and (min-width:900px){#aside-content .sticky_layout{position:sticky;position:-webkit-sticky;top:20px;-webkit-transition:top .3s;-moz-transition:top .3s;-o-transition:top .3s;-ms-transition:top .3s;transition:top .3s}}#aside-content .card-tag-cloud a{display:inline-block;padding:0 4px}#aside-content .card-tag-cloud a:hover{color:#49b1f5!important}#aside-content .aside-list>span{display:block;margin-bottom:10px;text-align:center}#aside-content .aside-list>.aside-list-item{display:-webkit-box;display:-moz-box;display:-webkit-flex;display:-ms-flexbox;display:box;display:flex;-webkit-box-align:center;-moz-box-align:center;-o-box-align:center;-ms-flex-align:center;-webkit-align-items:center;align-items:center;padding:6px 0}#aside-content .aside-list>.aside-list-item:first-child{padding-top:0}#aside-content .aside-list>.aside-list-item:not(:last-child){border-bottom:1px dashed #f5f5f5}#aside-content .aside-list>.aside-list-item:last-child{padding-bottom:0}#aside-content .aside-list>.aside-list-item .thumbnail{overflow:hidden;width:4.2em;height:4.2em}#aside-content .aside-list>.aside-list-item .content{-webkit-box-flex:1;-moz-box-flex:1;-o-box-flex:1;box-flex:1;-webkit-flex:1;-ms-flex:1;flex:1;padding-left:10px;word-break:break-all}#aside-content .aside-list>.aside-list-item .content>.name{-webkit-line-clamp:1}#aside-content .aside-list>.aside-list-item .content>.name,#aside-content .aside-list>.aside-list-item .content>time{display:block;color:#858585;font-size:85%}#aside-content .aside-list>.aside-list-item .content>.comment,#aside-content .aside-list>.aside-list-item .content>.title{color:var(--font-color);font-size:95%;line-height:1.5;-webkit-line-clamp:2}#aside-content .aside-list>.aside-list-item .content>.comment:hover,#aside-content .aside-list>.aside-list-item .content>.title:hover{color:#49b1f5}#aside-content .aside-list>.aside-list-item.no-cover{min-height:4.4em}#aside-content .card-archives ul.card-archive-list,#aside-content .card-categories ul.card-category-list{margin:0;padding:0;list-style:none}#aside-content .card-archives ul.card-archive-list>.card-archive-list-item a,#aside-content .card-categories ul.card-category-list>.card-category-list-item a{display:-webkit-box;display:-moz-box;display:-webkit-flex;display:-ms-flexbox;display:box;display:flex;-webkit-box-orient:horizontal;-moz-box-orient:horizontal;-o-box-orient:horizontal;-webkit-flex-direction:row;-ms-flex-direction:row;flex-direction:row;padding:3px 10px;color:var(--font-color);-webkit-transition:all .4s;-moz-transition:all .4s;-o-transition:all .4s;-ms-transition:all .4s;transition:all .4s}#aside-content .card-archives ul.card-archive-list>.card-archive-list-item a:hover,#aside-content .card-categories ul.card-category-list>.card-category-list-item a:hover{padding:3px 17px;background-color:var(--text-bg-hover)}#aside-content .card-archives ul.card-archive-list>.card-archive-list-item a span:first-child,#aside-content .card-categories ul.card-category-list>.card-category-list-item a span:first-child{-webkit-box-flex:1;-moz-box-flex:1;-o-box-flex:1;box-flex:1;-webkit-flex:1;-ms-flex:1;flex:1}#aside-content .card-categories .card-category-list.child{padding:0 0 0 16px}#aside-content .card-categories .card-category-list>.parent>a .card-category-list-name{width:70%!important}#aside-content .card-categories .card-category-list>.parent>a .card-category-list-count{width:calc(100% - 70% - 20px);text-align:right}#aside-content .card-categories .card-category-list>.parent i{float:right;margin-right:-.5em;padding:.5em;-webkit-transition:-webkit-transform .3s;-moz-transition:-moz-transform .3s;-o-transition:-o-transform .3s;-ms-transition:-ms-transform .3s;transition:transform .3s;-webkit-transform:rotate(0);-moz-transform:rotate(0);-o-transform:rotate(0);-ms-transform:rotate(0);transform:rotate(0)}#aside-content .card-categories .card-category-list>.parent i.expand{-webkit-transform:rotate(-90deg);-moz-transform:rotate(-90deg);-o-transform:rotate(-90deg);-ms-transform:rotate(-90deg);transform:rotate(-90deg)}#aside-content .card-webinfo .webinfo .webinfo-item{display:-webkit-box;display:-moz-box;display:-webkit-flex;display:-ms-flexbox;display:box;display:flex;-webkit-box-align:center;-moz-box-align:center;-o-box-align:center;-ms-flex-align:center;-webkit-align-items:center;align-items:center;padding:2px 10px 0}#aside-content .card-webinfo .webinfo .webinfo-item div:first-child{-webkit-box-flex:1;-moz-box-flex:1;-o-box-flex:1;box-flex:1;-webkit-flex:1;-ms-flex:1;flex:1;padding-right:20px}@media screen and (min-width:901px){#aside-content #card-toc{right:0!important}}@media screen and (max-width:900px){#aside-content #card-toc{position:fixed;right:-100%;bottom:30px;z-index:100;max-width:380px;max-height:calc(100% - 60px);width:calc(100% - 80px);opacity:0;-webkit-transition:initial;-moz-transition:initial;-o-transition:initial;-ms-transition:initial;transition:initial;-webkit-transform-origin:right bottom;-moz-transform-origin:right bottom;-o-transform-origin:right bottom;-ms-transform-origin:right bottom;transform-origin:right bottom}}#aside-content #card-toc .toc-percentage{float:right;margin-top:-9px;color:#a9a9a9;font-style:italic;font-size:140%}#aside-content #card-toc .toc-content{overflow-y:scroll;overflow-y:overlay;margin:0 -24px;max-height:calc(100vh - 120px)}@media screen and (max-width:900px){#aside-content #card-toc .toc-content{max-height:calc(100vh - 140px)}}#aside-content #card-toc .toc-content>*{margin:0 20px!important}#aside-content #card-toc .toc-content>*>.toc-item>.toc-child{margin-left:10px;padding-left:10px;border-left:1px solid var(--dark-grey)}#aside-content #card-toc .toc-content:not(.is-expand) .toc-child{display:none}@media screen and (max-width:900px){#aside-content #card-toc .toc-content:not(.is-expand) .toc-child{display:block!important}}#aside-content #card-toc .toc-content:not(.is-expand) .toc-item.active .toc-child{display:block}#aside-content #card-toc .toc-content li,#aside-content #card-toc .toc-content ol{list-style:none}#aside-content #card-toc .toc-content>ol{padding:0!important}#aside-content #card-toc .toc-content ol{margin:0;padding-left:18px}#aside-content #card-toc .toc-content .toc-link{display:block;margin:4px 0;padding:1px 6px;color:var(--toc-link-color);-webkit-transition:all .2s ease-in-out;-moz-transition:all .2s ease-in-out;-o-transition:all .2s ease-in-out;-ms-transition:all .2s ease-in-out;transition:all .2s ease-in-out}#aside-content #card-toc .toc-content .toc-link:hover{color:#49b1f5}#aside-content #card-toc .toc-content .toc-link.active{background:#00c4b6;color:#fff}#aside-content :only-child>.card-widget{margin-top:0}#aside-content .card-more-btn{float:right;color:inherit}#aside-content .card-more-btn:hover{-webkit-animation:more-btn-move 1s infinite;-moz-animation:more-btn-move 1s infinite;-o-animation:more-btn-move 1s infinite;-ms-animation:more-btn-move 1s infinite;animation:more-btn-move 1s infinite}#aside-content .card-announcement .item-headline i{color:red}.avatar-img{overflow:hidden;margin:0 auto;width:110px;height:110px;border-radius:70px}.avatar-img img{width:100%;height:100%;-webkit-transition:filter 375ms ease-in .2s,-webkit-transform .3s;-moz-transition:filter 375ms ease-in .2s,-moz-transform .3s;-o-transition:filter 375ms ease-in .2s,-o-transform .3s;-ms-transition:filter 375ms ease-in .2s,-ms-transform .3s;transition:filter 375ms ease-in .2s,transform .3s;object-fit:cover}.avatar-img img:hover{-webkit-transform:rotate(360deg);-moz-transform:rotate(360deg);-o-transform:rotate(360deg);-ms-transform:rotate(360deg);transform:rotate(360deg)}.site-data{display:table;width:100%;table-layout:fixed}.site-data>a{display:table-cell}.site-data>a div{-webkit-transition:all .3s;-moz-transition:all .3s;-o-transition:all .3s;-ms-transition:all .3s;transition:all .3s}.site-data>a:hover div{color:#49b1f5!important}.site-data>a .headline{color:var(--font-color)}.site-data>a .length-num{margin-top:-.32em;color:var(--text-highlight-color);font-size:1.4em}@media screen and (min-width:900px){html.hide-aside .layout{-webkit-box-pack:center;-moz-box-pack:center;-o-box-pack:center;-ms-flex-pack:center;-webkit-justify-content:center;justify-content:center}html.hide-aside .layout>.aside-content{display:none}html.hide-aside .layout>div:first-child{width:80%}}.page .sticky_layout{display:-webkit-box;display:-moz-box;display:-webkit-flex;display:-ms-flexbox;display:box;display:flex;-webkit-box-orient:vertical;-moz-box-orient:vertical;-o-box-orient:vertical;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column}@-moz-keyframes more-btn-move{0%,100%{-webkit-transform:translateX(0);-moz-transform:translateX(0);-o-transform:translateX(0);-ms-transform:translateX(0);transform:translateX(0)}50%{-webkit-transform:translateX(3px);-moz-transform:translateX(3px);-o-transform:translateX(3px);-ms-transform:translateX(3px);transform:translateX(3px)}}@-webkit-keyframes more-btn-move{0%,100%{-webkit-transform:translateX(0);-moz-transform:translateX(0);-o-transform:translateX(0);-ms-transform:translateX(0);transform:translateX(0)}50%{-webkit-transform:translateX(3px);-moz-transform:translateX(3px);-o-transform:translateX(3px);-ms-transform:translateX(3px);transform:translateX(3px)}}@-o-keyframes more-btn-move{0%,100%{-webkit-transform:translateX(0);-moz-transform:translateX(0);-o-transform:translateX(0);-ms-transform:translateX(0);transform:translateX(0)}50%{-webkit-transform:translateX(3px);-moz-transform:translateX(3px);-o-transform:translateX(3px);-ms-transform:translateX(3px);transform:translateX(3px)}}@keyframes more-btn-move{0%,100%{-webkit-transform:translateX(0);-moz-transform:translateX(0);-o-transform:translateX(0);-ms-transform:translateX(0);transform:translateX(0)}50%{-webkit-transform:translateX(3px);-moz-transform:translateX(3px);-o-transform:translateX(3px);-ms-transform:translateX(3px);transform:translateX(3px)}}@-moz-keyframes toc-open{0%{-webkit-transform:scale(.7);-moz-transform:scale(.7);-o-transform:scale(.7);-ms-transform:scale(.7);transform:scale(.7)}100%{-webkit-transform:scale(1);-moz-transform:scale(1);-o-transform:scale(1);-ms-transform:scale(1);transform:scale(1)}}@-webkit-keyframes toc-open{0%{-webkit-transform:scale(.7);-moz-transform:scale(.7);-o-transform:scale(.7);-ms-transform:scale(.7);transform:scale(.7)}100%{-webkit-transform:scale(1);-moz-transform:scale(1);-o-transform:scale(1);-ms-transform:scale(1);transform:scale(1)}}@-o-keyframes toc-open{0%{-webkit-transform:scale(.7);-moz-transform:scale(.7);-o-transform:scale(.7);-ms-transform:scale(.7);transform:scale(.7)}100%{-webkit-transform:scale(1);-moz-transform:scale(1);-o-transform:scale(1);-ms-transform:scale(1);transform:scale(1)}}@keyframes toc-open{0%{-webkit-transform:scale(.7);-moz-transform:scale(.7);-o-transform:scale(.7);-ms-transform:scale(.7);transform:scale(.7)}100%{-webkit-transform:scale(1);-moz-transform:scale(1);-o-transform:scale(1);-ms-transform:scale(1);transform:scale(1)}}@-moz-keyframes toc-close{0%{-webkit-transform:scale(1);-moz-transform:scale(1);-o-transform:scale(1);-ms-transform:scale(1);transform:scale(1)}100%{-webkit-transform:scale(.7);-moz-transform:scale(.7);-o-transform:scale(.7);-ms-transform:scale(.7);transform:scale(.7)}}@-webkit-keyframes toc-close{0%{-webkit-transform:scale(1);-moz-transform:scale(1);-o-transform:scale(1);-ms-transform:scale(1);transform:scale(1)}100%{-webkit-transform:scale(.7);-moz-transform:scale(.7);-o-transform:scale(.7);-ms-transform:scale(.7);transform:scale(.7)}}@-o-keyframes toc-close{0%{-webkit-transform:scale(1);-moz-transform:scale(1);-o-transform:scale(1);-ms-transform:scale(1);transform:scale(1)}100%{-webkit-transform:scale(.7);-moz-transform:scale(.7);-o-transform:scale(.7);-ms-transform:scale(.7);transform:scale(.7)}}@keyframes toc-close{0%{-webkit-transform:scale(1);-moz-transform:scale(1);-o-transform:scale(1);-ms-transform:scale(1);transform:scale(1)}100%{-webkit-transform:scale(.7);-moz-transform:scale(.7);-o-transform:scale(.7);-ms-transform:scale(.7);transform:scale(.7)}}#post-comment .comment-head{margin-bottom:20px}#post-comment .comment-head .comment-headline{display:inline-block;vertical-align:middle;font-weight:700;font-size:1.43em}#post-comment .comment-head #comment-switch{display:inline-block;float:right;margin:2px auto 0;padding:4px 16px;width:max-content;border-radius:8px;background:#f6f8fa}#post-comment .comment-head #comment-switch .first-comment{color:#49b1f5}#post-comment .comment-head #comment-switch .second-comment{color:#ff7242}#post-comment .comment-head #comment-switch .switch-btn{position:relative;display:inline-block;margin:-4px 8px 0;width:42px;height:22px;border-radius:34px;background-color:#49b1f5;vertical-align:middle;cursor:pointer;-webkit-transition:.4s;-moz-transition:.4s;-o-transition:.4s;-ms-transition:.4s;transition:.4s}#post-comment .comment-head #comment-switch .switch-btn:before{position:absolute;bottom:4px;left:4px;width:14px;height:14px;border-radius:50%;background-color:#fff;content:'';-webkit-transition:.4s;-moz-transition:.4s;-o-transition:.4s;-ms-transition:.4s;transition:.4s}#post-comment .comment-head #comment-switch .switch-btn.move{background-color:#ff7242}#post-comment .comment-head #comment-switch .switch-btn.move:before{-webkit-transform:translateX(20px);-moz-transform:translateX(20px);-o-transform:translateX(20px);-ms-transform:translateX(20px);transform:translateX(20px)}#post-comment .comment-wrap>div:nth-child(2){display:none}#footer{position:relative;background-color:#49b1f5;background-attachment:scroll;background-position:bottom;background-size:cover}#footer-wrap{position:relative;padding:40px 20px;color:var(--light-grey);text-align:center}#footer-wrap a{color:var(--light-grey)}#footer-wrap a:hover{text-decoration:underline}#footer-wrap .footer-separator{margin:0 4px}#footer-wrap .icp-icon{padding:0 4px;max-height:1.4em;width:auto;vertical-align:text-bottom}#page-header{position:relative;width:100%;background-color:#49b1f5;background-position:center center;background-size:cover;background-repeat:no-repeat;-webkit-transition:all .5s;-moz-transition:all .5s;-o-transition:all .5s;-ms-transition:all .5s;transition:all .5s}#page-header:not(.not-top-img):before{position:absolute;width:100%;height:100%;background-color:rgba(0,0,0,.3);content:''}#page-header.full_page{height:100vh;background-attachment:fixed}#page-header.full_page #site-info{position:absolute;top:43%;padding:0 10px;width:100%}#page-header #scroll-down .scroll-down-effects,#page-header #site-subtitle,#page-header #site-title{text-align:center;text-shadow:2px 2px 4px rgba(0,0,0,.15);line-height:1.5}#page-header #site-title{margin:0;color:var(--white);font-size:1.85em}@media screen and (min-width:768px){#page-header #site-title{font-size:2.85em}}#page-header #site-subtitle{color:var(--light-grey);font-size:1.15em}@media screen and (min-width:768px){#page-header #site-subtitle{font-size:1.72em}}#page-header #site_social_icons{display:none;margin:0 auto;width:300px;text-align:center}@media screen and (max-width:768px){#page-header #site_social_icons{display:block}}#page-header #site_social_icons .social-icon{margin:0 10px;color:var(--light-grey);text-shadow:2px 2px 4px rgba(0,0,0,.15);font-size:1.43em}#page-header #scroll-down{position:absolute;bottom:0;width:100%;cursor:pointer}#page-header #scroll-down .scroll-down-effects{position:relative;width:100%;color:var(--light-grey);font-size:30px}#page-header.not-home-page{height:400px}@media screen and (max-width:768px){#page-header.not-home-page{height:280px}}#page-header #page-site-info{position:absolute;top:200px;padding:0 10px;width:100%}@media screen and (max-width:768px){#page-header #page-site-info{top:140px}}#page-header.post-bg{height:400px}@media screen and (max-width:768px){#page-header.post-bg{height:360px}}#page-header.post-bg:before{background-color:rgba(0,0,0,.5)}#page-header #post-info{position:absolute;bottom:100px;padding:0 8%;width:100%;text-align:center}@media screen and (max-width:900px){#page-header #post-info{bottom:30px;text-align:left}}@media screen and (max-width:768px){#page-header #post-info{bottom:22px;padding:0 22px}}#page-header.not-top-img{margin-bottom:10px;height:60px;background:0}#page-header.not-top-img #nav{background:rgba(255,255,255,.8);-webkit-box-shadow:0 5px 6px -5px rgba(133,133,133,.6);box-shadow:0 5px 6px -5px rgba(133,133,133,.6)}#page-header.not-top-img #nav .site-name,#page-header.not-top-img #nav a{color:var(--font-color);text-shadow:none}#page-header.nav-fixed #nav{position:fixed;top:-60px;z-index:91;background:rgba(255,255,255,.8);-webkit-box-shadow:0 5px 6px -5px rgba(133,133,133,.6);box-shadow:0 5px 6px -5px rgba(133,133,133,.6);-webkit-transition:-webkit-transform .2s ease-in-out,opacity .2s ease-in-out;-moz-transition:-moz-transform .2s ease-in-out,opacity .2s ease-in-out;-o-transition:-o-transform .2s ease-in-out,opacity .2s ease-in-out;-ms-transition:-ms-transform .2s ease-in-out,opacity .2s ease-in-out;transition:transform .2s ease-in-out,opacity .2s ease-in-out}#page-header.nav-fixed #nav #blog-info{color:var(--font-color)}#page-header.nav-fixed #nav #blog-info:hover{color:#49b1f5}#page-header.nav-fixed #nav #blog-info .site-name{text-shadow:none}#page-header.nav-fixed #nav #toggle-menu,#page-header.nav-fixed #nav a{color:var(--font-color);text-shadow:none}#page-header.nav-fixed #nav #toggle-menu:hover,#page-header.nav-fixed #nav a:hover{color:#49b1f5}#page-header.nav-fixed.fixed #nav{top:0;-webkit-transition:all .5s;-moz-transition:all .5s;-o-transition:all .5s;-ms-transition:all .5s;transition:all .5s}#page-header.nav-visible:not(.fixed) #nav{-webkit-transition:all .5s;-moz-transition:all .5s;-o-transition:all .5s;-ms-transition:all .5s;transition:all .5s;-webkit-transform:translate3d(0,100%,0);-moz-transform:translate3d(0,100%,0);-o-transform:translate3d(0,100%,0);-ms-transform:translate3d(0,100%,0);transform:translate3d(0,100%,0)}#page-header.nav-visible:not(.fixed)+.layout>.aside-content>.sticky_layout{top:70px;-webkit-transition:top .5s;-moz-transition:top .5s;-o-transition:top .5s;-ms-transition:top .5s;transition:top .5s}#page-header.fixed #nav{position:fixed}#page-header.fixed+.layout>.aside-content>.sticky_layout{top:70px;-webkit-transition:top .5s;-moz-transition:top .5s;-o-transition:top .5s;-ms-transition:top .5s;transition:top .5s}#page-header.fixed+.layout #card-toc .toc-content{max-height:calc(100vh - 170px)}#page h1.page-title{margin:8px 0 20px}#post>#post-info{margin-bottom:30px}#post>#post-info .post-title{padding-bottom:4px;border-bottom:1px solid var(--light-grey);color:var(--text-highlight-color)}#post>#post-info .post-title .post-edit-link{float:right}#post>#post-info #post-meta,#post>#post-info #post-meta a{color:#78818a}#post-info .post-title{margin-bottom:8px;color:var(--white);font-weight:400;font-size:2.5em;line-height:1.5;-webkit-line-clamp:3}@media screen and (max-width:768px){#post-info .post-title{font-size:2.1em}}#post-info .post-title .post-edit-link{padding-left:10px}#post-info #post-meta{color:var(--light-grey);font-size:95%}@media screen and (min-width:768px){#post-info #post-meta>.meta-secondline>span:first-child{display:none}}@media screen and (max-width:768px){#post-info #post-meta{font-size:90%}#post-info #post-meta>.meta-firstline,#post-info #post-meta>.meta-secondline{display:inline}}#post-info #post-meta .post-meta-separator{margin:0 5px}#post-info #post-meta .post-meta-icon{margin-right:4px}#post-info #post-meta .post-meta-label{margin-right:4px}#post-info #post-meta a{color:var(--light-grey);-webkit-transition:all .3s ease-out;-moz-transition:all .3s ease-out;-o-transition:all .3s ease-out;-ms-transition:all .3s ease-out;transition:all .3s ease-out}#post-info #post-meta a:hover{color:#49b1f5;text-decoration:underline}#nav{position:absolute;top:0;z-index:90;display:-webkit-box;display:-moz-box;display:-webkit-flex;display:-ms-flexbox;display:box;display:flex;-webkit-box-align:center;-moz-box-align:center;-o-box-align:center;-ms-flex-align:center;-webkit-align-items:center;align-items:center;padding:0 36px;width:100%;height:60px;font-size:1.3em;opacity:0;-webkit-transition:all .5s;-moz-transition:all .5s;-o-transition:all .5s;-ms-transition:all .5s;transition:all .5s}@media screen and (max-width:768px){#nav{padding:0 16px}}#nav.show{opacity:1;-ms-filter:none;filter:none}#nav #blog-info{-webkit-box-flex:1;-moz-box-flex:1;-o-box-flex:1;box-flex:1;-webkit-flex:1;-ms-flex:1;flex:1;color:var(--light-grey)}#nav #blog-info .site-icon{margin-right:6px;height:36px;vertical-align:middle}#nav #toggle-menu{display:none;padding:2px 0 0 6px;vertical-align:top}#nav #toggle-menu:hover{color:var(--white)}#nav a{color:var(--light-grey)}#nav a:hover{color:var(--white)}#nav .site-name{text-shadow:2px 2px 4px rgba(0,0,0,.15);font-weight:700}#nav .menus_items{display:inline}#nav .menus_items .menus_item{position:relative;display:inline-block;padding:0 0 0 14px}#nav .menus_items .menus_item:hover .menus_item_child{display:block}#nav .menus_items .menus_item:hover>a>i:last-child{-webkit-transform:rotate(180deg);-moz-transform:rotate(180deg);-o-transform:rotate(180deg);-ms-transform:rotate(180deg);transform:rotate(180deg)}#nav .menus_items .menus_item>a>i:last-child{padding:4px;-webkit-transition:-webkit-transform .3s;-moz-transition:-moz-transform .3s;-o-transition:-o-transform .3s;-ms-transition:-ms-transform .3s;transition:transform .3s}#nav .menus_items .menus_item .menus_item_child{position:absolute;right:0;display:none;margin-top:8px;padding:0;width:max-content;border-radius:5px;background-color:var(--sidebar-bg);-webkit-box-shadow:0 5px 20px -4px rgba(0,0,0,.5);box-shadow:0 5px 20px -4px rgba(0,0,0,.5);-webkit-animation:sub_menus .3s .1s ease both;-moz-animation:sub_menus .3s .1s ease both;-o-animation:sub_menus .3s .1s ease both;-ms-animation:sub_menus .3s .1s ease both;animation:sub_menus .3s .1s ease both}#nav .menus_items .menus_item .menus_item_child:before{position:absolute;top:-8px;left:0;width:100%;height:20px;content:''}#nav .menus_items .menus_item .menus_item_child li{list-style:none}#nav .menus_items .menus_item .menus_item_child li:hover{background:var(--text-bg-hover)}#nav .menus_items .menus_item .menus_item_child li:first-child{border-top-left-radius:5px;border-top-right-radius:5px}#nav .menus_items .menus_item .menus_item_child li:last-child{border-bottom-right-radius:5px;border-bottom-left-radius:5px}#nav .menus_items .menus_item .menus_item_child li a{display:inline-block;padding:8px 16px;width:100%;color:var(--font-color)!important;text-shadow:none!important}#nav.hide-menu #toggle-menu{display:inline-block!important}#nav.hide-menu #toggle-menu .site-page{font-size:inherit}#nav.hide-menu .menus_items{display:none}#nav.hide-menu #search-button span{display:none}#nav #search-button{display:inline;padding:0 0 0 14px}#nav .site-page{position:relative;padding-bottom:6px;text-shadow:1px 1px 2px rgba(0,0,0,.3);font-size:.78em;cursor:pointer}#nav .site-page:not(.child):after{position:absolute;bottom:0;left:0;z-index:-1;width:0;height:3px;background-color:#80c8f8;content:'';-webkit-transition:all .3s ease-in-out;-moz-transition:all .3s ease-in-out;-o-transition:all .3s ease-in-out;-ms-transition:all .3s ease-in-out;transition:all .3s ease-in-out}#nav .site-page:not(.child):hover:after{width:100%}#pagination .pagination{margin-top:20px;text-align:center}#pagination .page-number.current{background:#00c4b6;color:var(--white)}#pagination .pagination-info{position:absolute;top:50%;padding:20px 40px;width:100%;-webkit-transform:translate(0,-50%);-moz-transform:translate(0,-50%);-o-transform:translate(0,-50%);-ms-transform:translate(0,-50%);transform:translate(0,-50%)}#pagination .next_info,#pagination .prev_info{color:var(--white);font-weight:500}#pagination .next-post .pagination-info{text-align:right}#pagination .pull-full{width:100%!important}#pagination .next-post .label,#pagination .prev-post .label{color:var(--light-grey);text-transform:uppercase;font-size:90%}#pagination .next-post,#pagination .prev-post{width:50%}@media screen and (max-width:768px){#pagination .next-post,#pagination .prev-post{width:100%}}#pagination .next-post a,#pagination .prev-post a{position:relative;display:block;overflow:hidden;height:150px}#pagination.pagination-post{overflow:hidden;margin-top:40px;width:100%;background:#000}.layout>.recent-posts .pagination>*{display:inline-block;margin:0 6px;width:2.5em;height:2.5em;line-height:2.5em}.layout>.recent-posts .pagination>:not(.space):hover{background:var(--btn-hover-color);color:var(--btn-color)}.layout>div:not(.recent-posts) .pagination .page-number{display:inline-block;margin:0 4px;min-width:24px;height:24px;text-align:center;line-height:24px;cursor:pointer}#article-container{word-wrap:break-word;overflow-wrap:break-word}#article-container a{color:#49b1f5}#article-container a:hover{text-decoration:underline}#article-container img{display:block;margin:0 auto 20px;max-width:100%;-webkit-transition:filter 375ms ease-in .2s;-moz-transition:filter 375ms ease-in .2s;-o-transition:filter 375ms ease-in .2s;-ms-transition:filter 375ms ease-in .2s;transition:filter 375ms ease-in .2s}#article-container p{margin:0 0 16px}#article-container iframe{margin:0 0 20px}#article-container kbd{margin:0 3px;padding:3px 5px;border:1px solid #b4b4b4;border-radius:3px;background-color:#f8f8f8;-webkit-box-shadow:0 1px 3px rgba(0,0,0,.25),0 2px 1px 0 rgba(255,255,255,.6) inset;box-shadow:0 1px 3px rgba(0,0,0,.25),0 2px 1px 0 rgba(255,255,255,.6) inset;color:#34495e;white-space:nowrap;font-weight:600;font-size:.9em;font-family:Monaco,'Ubuntu Mono',monospace;line-height:1em}#article-container ol ol,#article-container ol ul,#article-container ul ol,#article-container ul ul{padding-left:20px}#article-container ol li,#article-container ul li{margin:4px 0}#article-container ol p,#article-container ul p{margin:0 0 8px}#article-container h1,#article-container h2,#article-container h3,#article-container h4,#article-container h5,#article-container h6{-webkit-transition:all .2s ease-out;-moz-transition:all .2s ease-out;-o-transition:all .2s ease-out;-ms-transition:all .2s ease-out;transition:all .2s ease-out}#article-container h1:before,#article-container h2:before,#article-container h3:before,#article-container h4:before,#article-container h5:before,#article-container h6:before{position:absolute;top:calc(50% - 7px);color:#f47466;content:'\f0c1';line-height:1;-webkit-transition:all .2s ease-out;-moz-transition:all .2s ease-out;-o-transition:all .2s ease-out;-ms-transition:all .2s ease-out;transition:all .2s ease-out}#article-container h1:hover:before,#article-container h2:hover:before,#article-container h3:hover:before,#article-container h4:hover:before,#article-container h5:hover:before,#article-container h6:hover:before{color:#49b1f5}#article-container h1{padding-left:32px}#article-container h1:before{margin-left:-26px;font-size:20px}#article-container h1:hover{padding-left:38px}#article-container h2{padding-left:30px}#article-container h2:before{margin-left:-24px;font-size:18px}#article-container h2:hover{padding-left:36px}#article-container h3{padding-left:28px}#article-container h3:before{margin-left:-22px;font-size:16px}#article-container h3:hover{padding-left:34px}#article-container h4{padding-left:26px}#article-container h4:before{margin-left:-20px;font-size:14px}#article-container h4:hover{padding-left:32px}#article-container h5{padding-left:24px}#article-container h5:before{margin-left:-18px;font-size:12px}#article-container h5:hover{padding-left:30px}#article-container h6{padding-left:24px}#article-container h6:before{margin-left:-18px;font-size:12px}#article-container h6:hover{padding-left:30px}#article-container ol p,#article-container ul p{margin:0 0 8px}#article-container li::marker{color:#49b1f5;font-weight:600;font-size:1.05em}#article-container li:hover::marker{color:var(--pseudo-hover)}#article-container ul>li{list-style-type:circle}#article-container>:last-child{margin-bottom:0!important}#post .tag_share:after{display:block;clear:both;content:''}#post .tag_share .post-meta__tag-list{display:inline-block}#post .tag_share .post-meta__tags{display:inline-block;margin:8px 8px 8px 0;padding:0 12px;width:fit-content;border:1px solid #49b1f5;border-radius:12px;color:#49b1f5;font-size:.85em;-webkit-transition:all .2s ease-in-out;-moz-transition:all .2s ease-in-out;-o-transition:all .2s ease-in-out;-ms-transition:all .2s ease-in-out;transition:all .2s ease-in-out}#post .tag_share .post-meta__tags:hover{background:#49b1f5;color:var(--white)}#post .tag_share .post_share{display:inline-block;float:right;margin:8px 0 0;width:fit-content}#post .tag_share .post_share .social-share{font-size:.85em}#post .tag_share .post_share .social-share .social-share-icon{margin:0 4px;width:1.85em;height:1.85em;font-size:1.2em;line-height:1.85em}#post .post-copyright{position:relative;margin:40px 0 10px;padding:10px 16px;border:1px solid var(--light-grey);-webkit-transition:box-shadow .3s ease-in-out;-moz-transition:box-shadow .3s ease-in-out;-o-transition:box-shadow .3s ease-in-out;-ms-transition:box-shadow .3s ease-in-out;transition:box-shadow .3s ease-in-out}#post .post-copyright:before{position:absolute;top:2px;right:12px;color:#49b1f5;content:'\f1f9';font-size:1.3em}#post .post-copyright:hover{-webkit-box-shadow:0 0 8px 0 rgba(232,237,250,.6),0 2px 4px 0 rgba(232,237,250,.5);box-shadow:0 0 8px 0 rgba(232,237,250,.6),0 2px 4px 0 rgba(232,237,250,.5)}#post .post-copyright .post-copyright-meta{color:#49b1f5;font-weight:700}#post .post-copyright .post-copyright-info{padding-left:6px}#post .post-copyright .post-copyright-info a{text-decoration:underline;word-break:break-word}#post .post-copyright .post-copyright-info a:hover{text-decoration:none}#post .post-outdate-notice{position:relative;margin:0 0 20px;padding:.5em 1.2em;border-radius:3px;background-color:#ffe6e6;color:#f66;padding:.5em 1em .5em 2.6em;border-left:5px solid #ff8080}#post .post-outdate-notice:before{position:absolute;top:50%;left:.9em;color:#ff8080;content:'\f071';-webkit-transform:translateY(-50%);-moz-transform:translateY(-50%);-o-transform:translateY(-50%);-ms-transform:translateY(-50%);transform:translateY(-50%)}#post .ads-wrap{margin:40px 0}.relatedPosts{margin-top:40px}.relatedPosts>.headline{margin-bottom:5px;font-weight:700;font-size:1.43em}.relatedPosts>.relatedPosts-list>div{position:relative;display:inline-block;overflow:hidden;margin:3px;width:calc(33.333% - 6px);height:200px;background:#000;vertical-align:bottom}@media screen and (max-width:768px){.relatedPosts>.relatedPosts-list>div{margin:2px;width:calc(50% - 4px);height:150px}}@media screen and (max-width:600px){.relatedPosts>.relatedPosts-list>div{width:calc(100% - 4px)}}.relatedPosts>.relatedPosts-list .content{position:absolute;top:50%;padding:0 20px;width:100%;-webkit-transform:translate(0,-50%);-moz-transform:translate(0,-50%);-o-transform:translate(0,-50%);-ms-transform:translate(0,-50%);transform:translate(0,-50%)}.relatedPosts>.relatedPosts-list .content .date{color:var(--light-grey);font-size:90%}.relatedPosts>.relatedPosts-list .content .title{color:var(--white);-webkit-line-clamp:2}.post-reward{position:relative;margin-top:80px;width:100%;text-align:center;pointer-events:none}.post-reward>*{pointer-events:auto}.post-reward .reward-button{display:inline-block;padding:4px 24px;background:var(--btn-bg);color:var(--btn-color);cursor:pointer}.post-reward:hover .reward-button{background:var(--btn-hover-color)}.post-reward:hover>.reward-main{display:block}.post-reward .reward-main{position:absolute;bottom:40px;left:0;z-index:100;display:none;padding:0 0 15px;width:100%}.post-reward .reward-main .reward-all{display:inline-block;margin:0;padding:20px 10px;border-radius:4px;background:var(--reward-pop)}.post-reward .reward-main .reward-all:before{position:absolute;bottom:-10px;left:0;width:100%;height:20px;content:''}.post-reward .reward-main .reward-all:after{position:absolute;right:0;bottom:2px;left:0;margin:0 auto;width:0;height:0;border-top:13px solid var(--reward-pop);border-right:13px solid transparent;border-left:13px solid transparent;content:''}.post-reward .reward-main .reward-all .reward-item{display:inline-block;padding:0 8px;list-style-type:none;vertical-align:top}.post-reward .reward-main .reward-all .reward-item img{width:130px;height:130px}.post-reward .reward-main .reward-all .reward-item .post-qr-code-desc{width:130px;color:#858585}#rightside{position:fixed;right:-48px;bottom:40px;z-index:100;opacity:0;-webkit-transition:all .5s;-moz-transition:all .5s;-o-transition:all .5s;-ms-transition:all .5s;transition:all .5s}#rightside #rightside-config-hide{height:0;opacity:0;-webkit-transition:-webkit-transform .4s;-moz-transition:-moz-transform .4s;-o-transition:-o-transform .4s;-ms-transition:-ms-transform .4s;transition:transform .4s;-webkit-transform:translate(45px,0);-moz-transform:translate(45px,0);-o-transform:translate(45px,0);-ms-transform:translate(45px,0);transform:translate(45px,0)}#rightside #rightside-config-hide.show{height:auto;opacity:1;-ms-filter:none;filter:none;-webkit-transform:translate(0,0);-moz-transform:translate(0,0);-o-transform:translate(0,0);-ms-transform:translate(0,0);transform:translate(0,0)}#rightside #rightside-config-hide.status{height:auto;opacity:1;-ms-filter:none;filter:none}#rightside>div>a,#rightside>div>button{display:block;margin-bottom:5px;width:35px;height:35px;border-radius:5px;background-color:var(--btn-bg);color:var(--btn-color);text-align:center;font-size:16px;line-height:35px}#rightside>div>a:hover,#rightside>div>button:hover{background-color:var(--btn-hover-color)}#rightside #mobile-toc-button{display:none}@media screen and (max-width:900px){#rightside #mobile-toc-button{display:block}}@media screen and (max-width:900px){#rightside #hide-aside-btn{display:none}}#sidebar #menu-mask{position:fixed;z-index:102;display:none;width:100%;height:100%;background:rgba(0,0,0,.8)}#sidebar #sidebar-menus{position:fixed;top:0;right:-300px;z-index:103;overflow-x:hidden;overflow-y:auto;width:300px;height:100%;background:var(--sidebar-bg);-webkit-transition:all .5s;-moz-transition:all .5s;-o-transition:all .5s;-ms-transition:all .5s;transition:all .5s}#sidebar #sidebar-menus.open{-webkit-transform:translate3d(-100%,0,0);-moz-transform:translate3d(-100%,0,0);-o-transform:translate3d(-100%,0,0);-ms-transform:translate3d(-100%,0,0);transform:translate3d(-100%,0,0)}#sidebar #sidebar-menus>.avatar-img{margin:20px auto}#sidebar #sidebar-menus .sidebar-site-data{padding:0 10px}#sidebar #sidebar-menus hr{margin:20px auto}#sidebar #sidebar-menus .menus_items{padding:0 10px 40px}#sidebar #sidebar-menus .menus_items .site-page{position:relative;display:block;padding:6px 30px 6px 22px;color:var(--font-color);font-size:1.15em}#sidebar #sidebar-menus .menus_items .site-page:hover{background:var(--text-bg-hover)}#sidebar #sidebar-menus .menus_items .site-page i:first-child{width:15%;text-align:left}#sidebar #sidebar-menus .menus_items .site-page.group>i:last-child{position:absolute;top:.78em;right:18px;-webkit-transition:-webkit-transform .3s;-moz-transition:-moz-transform .3s;-o-transition:-o-transform .3s;-ms-transition:-ms-transform .3s;transition:transform .3s}#sidebar #sidebar-menus .menus_items .site-page.group.hide>i:last-child{-webkit-transform:rotate(90deg);-moz-transform:rotate(90deg);-o-transform:rotate(90deg);-ms-transform:rotate(90deg);transform:rotate(90deg)}#sidebar #sidebar-menus .menus_items .site-page.group.hide+.menus_item_child{display:none}#sidebar #sidebar-menus .menus_items .menus_item_child{margin:0;list-style:none}#vcomment{font-size:1.1em}#vcomment .vbtn{border:none;background:var(--btn-bg);color:var(--btn-color)}#vcomment .vbtn:hover{background:var(--btn-hover-color)}#vcomment .vimg{-webkit-transition:all .3s;-moz-transition:all .3s;-o-transition:all .3s;-ms-transition:all .3s;transition:all .3s}#vcomment .vimg:hover{-webkit-transform:rotate(360deg);-moz-transform:rotate(360deg);-o-transform:rotate(360deg);-ms-transform:rotate(360deg);transform:rotate(360deg)}#vcomment .vcards .vcard .vcontent.expand:after,#vcomment .vcards .vcard .vcontent.expand:before{z-index:22}#waline-wrap{--waline-font-size:1.1em;--waline-theme-color:#49b1f5;--waline-active-color:#ff7242}#waline-wrap .wl-comment-actions>button:not(last-child){padding-right:4px}.fireworks{position:fixed;top:0;left:0;z-index:9999;pointer-events:none}.medium-zoom-image--opened{z-index:99999!important;margin:0!important}.medium-zoom-overlay{z-index:99999!important}.mermaid-wrap{margin:0 0 20px;text-align:center}.mermaid-wrap>svg{height:100%}.fb-comments iframe,.utterances{width:100%!important}#gitalk-container .gt-meta{margin:0 0 .8em;padding:6px 0 16px}.katex-wrap{overflow:auto}.katex-wrap::-webkit-scrollbar{display:none}.mathjax-overflow{overflow-x:auto;overflow-y:hidden}span.mathjax-overflow{display:inline-block;padding:0 2px;max-width:100%;vertical-align:bottom}.aplayer{color:#4c4948}#article-container .aplayer{margin:0 0 20px}#article-container .aplayer ol,#article-container .aplayer ul{margin:0;padding:0}#article-container .aplayer ol li,#article-container .aplayer ul li{margin:0;padding:0 15px}#article-container .aplayer ol li:before,#article-container .aplayer ul li:before{content:none}.snackbar-css{border-radius:5px!important}#article-container .btn-center{margin:0 0 20px;text-align:center}#article-container .btn-beautify{display:inline-block;margin:0 4px 6px;padding:0 15px;background-color:var(--btn-beautify-color,#777);color:#fff;line-height:2}#article-container .btn-beautify.blue{--btn-beautify-color:#428bca}#article-container .btn-beautify.pink{--btn-beautify-color:#ff69b4}#article-container .btn-beautify.red{--btn-beautify-color:#f00}#article-container .btn-beautify.purple{--btn-beautify-color:#6f42c1}#article-container .btn-beautify.orange{--btn-beautify-color:#ff8c00}#article-container .btn-beautify.green{--btn-beautify-color:#5cb85c}#article-container .btn-beautify:hover{background-color:var(--btn-hover-color)}#article-container .btn-beautify i+span{margin-left:6px}#article-container .btn-beautify:not(.block)+.btn-beautify:not(.block){margin:0 4px 20px}#article-container .btn-beautify.block{display:block;margin:0 0 20px;width:fit-content;width:-moz-fit-content}#article-container .btn-beautify.block.center{margin:0 auto 20px}#article-container .btn-beautify.block.right{margin:0 0 20px auto}#article-container .btn-beautify.larger{padding:6px 15px}#article-container .btn-beautify:hover{text-decoration:none}#article-container .btn-beautify.outline{border:1px solid transparent;border-color:var(--btn-beautify-color,#777);background-color:transparent;color:var(--btn-beautify-color,#777)}#article-container .btn-beautify.outline:hover{background-color:var(--btn-beautify-color,#777)}#article-container .btn-beautify.outline:hover{color:#fff!important}#article-container figure.gallery-group{position:relative;float:left;overflow:hidden;margin:6px 4px;width:calc(50% - 8px);height:250px;border-radius:8px;background:#000;-webkit-transform:translate3d(0,0,0)}@media screen and (max-width:600px){#article-container figure.gallery-group{width:calc(100% - 8px)}}#article-container figure.gallery-group:hover img{opacity:.4;-webkit-transform:translate3d(0,0,0);-moz-transform:translate3d(0,0,0);-o-transform:translate3d(0,0,0);-ms-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}#article-container figure.gallery-group:hover .gallery-group-name::after{-webkit-transform:translate3d(0,0,0);-moz-transform:translate3d(0,0,0);-o-transform:translate3d(0,0,0);-ms-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}#article-container figure.gallery-group:hover p{opacity:1;-ms-filter:none;filter:none;-webkit-transform:translate3d(0,0,0);-moz-transform:translate3d(0,0,0);-o-transform:translate3d(0,0,0);-ms-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}#article-container figure.gallery-group img{position:relative;margin:0;max-width:none;width:calc(100% + 20px);height:250px;-webkit-backface-visibility:hidden;-moz-backface-visibility:hidden;-ms-backface-visibility:hidden;backface-visibility:hidden;opacity:.8;-webkit-transition:all .3s,filter 375ms ease-in .2s;-moz-transition:all .3s,filter 375ms ease-in .2s;-o-transition:all .3s,filter 375ms ease-in .2s;-ms-transition:all .3s,filter 375ms ease-in .2s;transition:all .3s,filter 375ms ease-in .2s;-webkit-transform:translate3d(-10px,0,0);-moz-transform:translate3d(-10px,0,0);-o-transform:translate3d(-10px,0,0);-ms-transform:translate3d(-10px,0,0);transform:translate3d(-10px,0,0);object-fit:cover}#article-container figure.gallery-group figcaption{position:absolute;top:0;left:0;padding:30px;width:100%;height:100%;color:#fff;text-transform:uppercase;-webkit-backface-visibility:hidden;-moz-backface-visibility:hidden;-ms-backface-visibility:hidden;backface-visibility:hidden}#article-container figure.gallery-group figcaption>a{position:absolute;top:0;right:0;bottom:0;left:0;z-index:1000;opacity:0}#article-container figure.gallery-group p{margin:0;padding:8px 0 0;letter-spacing:1px;font-size:1.1em;line-height:1.5;opacity:0;-webkit-transition:opacity .35s,-webkit-transform .35s;-moz-transition:opacity .35s,-moz-transform .35s;-o-transition:opacity .35s,-o-transform .35s;-ms-transition:opacity .35s,-ms-transform .35s;transition:opacity .35s,transform .35s;-webkit-transform:translate3d(100%,0,0);-moz-transform:translate3d(100%,0,0);-o-transform:translate3d(100%,0,0);-ms-transform:translate3d(100%,0,0);transform:translate3d(100%,0,0);-webkit-line-clamp:4}#article-container figure.gallery-group .gallery-group-name{position:relative;margin:0;padding:8px 0;font-weight:700;font-size:1.65em;line-height:1.5;-webkit-line-clamp:2}#article-container figure.gallery-group .gallery-group-name:after{position:absolute;bottom:0;left:0;width:100%;height:2px;background:#fff;content:'';-webkit-transition:-webkit-transform .35s;-moz-transition:-moz-transform .35s;-o-transition:-o-transform .35s;-ms-transition:-ms-transform .35s;transition:transform .35s;-webkit-transform:translate3d(-100%,0,0);-moz-transform:translate3d(-100%,0,0);-o-transform:translate3d(-100%,0,0);-ms-transform:translate3d(-100%,0,0);transform:translate3d(-100%,0,0)}#article-container .gallery-group-main{overflow:auto;padding:0 0 16px}#article-container .gallery{margin:0 0 16px;text-align:center}#article-container .gallery .fj-gallery{opacity:0}#article-container .gallery .fj-gallery .img-alt{display:none}#article-container .gallery .fj-gallery.lazyload+button{display:inline-block}#article-container .gallery .fj-gallery .gallery-data{display:none}#article-container .gallery button{display:none;margin-top:25px;padding:10px;width:9em;border-radius:5px;background:var(--btn-bg);color:var(--btn-color);font-weight:700;font-size:1.1em;-webkit-transition:all .3s;-moz-transition:all .3s;-o-transition:all .3s;-ms-transition:all .3s;transition:all .3s}#article-container .gallery button>*{-webkit-transition:all .4s;-moz-transition:all .4s;-o-transition:all .4s;-ms-transition:all .4s;transition:all .4s}#article-container .gallery button i{width:0;opacity:0}#article-container .gallery button:hover{background:var(--btn-hover-color)}#article-container .gallery button:hover i{margin-left:2px;width:20px;opacity:1;-ms-filter:none;filter:none}blockquote.pullquote{position:relative;max-width:45%;font-size:110%}blockquote.pullquote.left{float:left;margin:1em .5em 0 0}blockquote.pullquote.right{float:right;margin:1em 0 0 .5em}.video-container{position:relative;overflow:hidden;margin-bottom:16px;padding-top:56.25%;height:0}.video-container iframe{position:absolute;top:0;left:0;margin-top:0;width:100%;height:100%}.hide-block>.hide-button,.hide-inline>.hide-button{display:inline-block;padding:5px 18px;background:#49b1f5;color:var(--white)}.hide-block>.hide-button:hover,.hide-inline>.hide-button:hover{background-color:var(--btn-hover-color)}.hide-block>.hide-button.open,.hide-inline>.hide-button.open{display:none}.hide-block>.hide-button.open+div,.hide-inline>.hide-button.open+div{display:block}.hide-block>.hide-button.open+span,.hide-inline>.hide-button.open+span{display:inline}.hide-block>.hide-content,.hide-inline>.hide-content{display:none}.hide-inline>.hide-button{margin:0 6px}.hide-inline>.hide-content{margin:0 6px}.hide-block{margin:0 0 16px}.toggle{margin-bottom:20px;border:1px solid #f0f0f0}.toggle>.toggle-button{padding:6px 15px;background:#f0f0f0;color:#1f2d3d;cursor:pointer}.toggle>.toggle-content{margin:30px 24px}#article-container .inline-img{display:inline;margin:0 3px;height:1.1em;vertical-align:text-bottom}.hl-label{padding:2px 4px;border-radius:3px;color:#fff}.hl-label.default{background-color:#777}.hl-label.blue{background-color:#428bca}.hl-label.pink{background-color:#ff69b4}.hl-label.red{background-color:red}.hl-label.purple{background-color:#6f42c1}.hl-label.orange{background-color:#ff8c00}.hl-label.green{background-color:#5cb85c}.note{position:relative;margin:0 0 20px;padding:15px;border-radius:3px}.note.icon-padding{padding-left:3em}.note>.note-icon{position:absolute;top:calc(50% - .5em);left:.8em;font-size:larger}.note.blue:not(.disabled){border-left-color:#428bca!important}.note.blue:not(.disabled).modern{border-left-color:transparent!important;color:#428bca}.note.blue:not(.disabled):not(.simple){background:#e3eef7!important}.note.blue>.note-icon{color:#428bca}.note.pink:not(.disabled){border-left-color:#ff69b4!important}.note.pink:not(.disabled).modern{border-left-color:transparent!important;color:#ff69b4}.note.pink:not(.disabled):not(.simple){background:#ffe9f4!important}.note.pink>.note-icon{color:#ff69b4}.note.red:not(.disabled){border-left-color:red!important}.note.red:not(.disabled).modern{border-left-color:transparent!important;color:red}.note.red:not(.disabled):not(.simple){background:#ffd9d9!important}.note.red>.note-icon{color:red}.note.purple:not(.disabled){border-left-color:#6f42c1!important}.note.purple:not(.disabled).modern{border-left-color:transparent!important;color:#6f42c1}.note.purple:not(.disabled):not(.simple){background:#e9e3f6!important}.note.purple>.note-icon{color:#6f42c1}.note.orange:not(.disabled){border-left-color:#ff8c00!important}.note.orange:not(.disabled).modern{border-left-color:transparent!important;color:#ff8c00}.note.orange:not(.disabled):not(.simple){background:#ffeed9!important}.note.orange>.note-icon{color:#ff8c00}.note.green:not(.disabled){border-left-color:#5cb85c!important}.note.green:not(.disabled).modern{border-left-color:transparent!important;color:#5cb85c}.note.green:not(.disabled):not(.simple){background:#e7f4e7!important}.note.green>.note-icon{color:#5cb85c}.note.simple{border:1px solid #eee;border-left-width:5px}.note.modern{border:1px solid transparent!important;background-color:#f5f5f5;color:#4c4948}.note.flat{border:initial;border-left:5px solid #eee;background-color:#f9f9f9;color:#4c4948}.note h2,.note h3,.note h4,.note h5,.note h6{margin-top:3px;margin-bottom:0;padding-top:0!important;border-bottom:initial}.note blockquote:first-child,.note img:first-child,.note ol:first-child,.note p:first-child,.note pre:first-child,.note table:first-child,.note ul:first-child{margin-top:0!important}.note blockquote:last-child,.note img:last-child,.note ol:last-child,.note p:last-child,.note pre:last-child,.note table:last-child,.note ul:last-child{margin-bottom:0!important}.note:not(.no-icon){padding-left:3em}.note:not(.no-icon)::before{position:absolute;top:calc(50% - .95em);left:.8em;font-size:larger}.note.default.flat{background:#f7f7f7}.note.default.modern{border-color:#e1e1e1;background:#f3f3f3;color:#666}.note.default.modern a:not(.btn){color:#666}.note.default.modern a:not(.btn):hover{color:#454545}.note.default:not(.modern){border-left-color:#777}.note.default:not(.modern) h2,.note.default:not(.modern) h3,.note.default:not(.modern) h4,.note.default:not(.modern) h5,.note.default:not(.modern) h6{color:#777}.note.default:not(.no-icon)::before{content:'\f0a9'}.note.default:not(.no-icon):not(.modern)::before{color:#777}.note.primary.flat{background:#f5f0fa}.note.primary.modern{border-color:#e1c2ff;background:#f3daff;color:#6f42c1}.note.primary.modern a:not(.btn){color:#6f42c1}.note.primary.modern a:not(.btn):hover{color:#453298}.note.primary:not(.modern){border-left-color:#6f42c1}.note.primary:not(.modern) h2,.note.primary:not(.modern) h3,.note.primary:not(.modern) h4,.note.primary:not(.modern) h5,.note.primary:not(.modern) h6{color:#6f42c1}.note.primary:not(.no-icon)::before{content:'\f055'}.note.primary:not(.no-icon):not(.modern)::before{color:#6f42c1}.note.info.flat{background:#eef7fa}.note.info.modern{border-color:#b3e5ef;background:#d9edf7;color:#31708f}.note.info.modern a:not(.btn){color:#31708f}.note.info.modern a:not(.btn):hover{color:#215761}.note.info:not(.modern){border-left-color:#428bca}.note.info:not(.modern) h2,.note.info:not(.modern) h3,.note.info:not(.modern) h4,.note.info:not(.modern) h5,.note.info:not(.modern) h6{color:#428bca}.note.info:not(.no-icon)::before{content:'\f05a'}.note.info:not(.no-icon):not(.modern)::before{color:#428bca}.note.success.flat{background:#eff8f0}.note.success.modern{border-color:#d0e6be;background:#dff0d8;color:#3c763d}.note.success.modern a:not(.btn){color:#3c763d}.note.success.modern a:not(.btn):hover{color:#32562c}.note.success:not(.modern){border-left-color:#5cb85c}.note.success:not(.modern) h2,.note.success:not(.modern) h3,.note.success:not(.modern) h4,.note.success:not(.modern) h5,.note.success:not(.modern) h6{color:#5cb85c}.note.success:not(.no-icon)::before{content:'\f058'}.note.success:not(.no-icon):not(.modern)::before{color:#5cb85c}.note.warning.flat{background:#fdf8ea}.note.warning.modern{border-color:#fae4cd;background:#fcf4e3;color:#8a6d3b}.note.warning.modern a:not(.btn){color:#8a6d3b}.note.warning.modern a:not(.btn):hover{color:#714f30}.note.warning:not(.modern){border-left-color:#f0ad4e}.note.warning:not(.modern) h2,.note.warning:not(.modern) h3,.note.warning:not(.modern) h4,.note.warning:not(.modern) h5,.note.warning:not(.modern) h6{color:#f0ad4e}.note.warning:not(.no-icon)::before{content:'\f06a'}.note.warning:not(.no-icon):not(.modern)::before{color:#f0ad4e}.note.danger.flat{background:#fcf1f2}.note.danger.modern{border-color:#ebcdd2;background:#f2dfdf;color:#a94442}.note.danger.modern a:not(.btn){color:#a94442}.note.danger.modern a:not(.btn):hover{color:#84333f}.note.danger:not(.modern){border-left-color:#d9534f}.note.danger:not(.modern) h2,.note.danger:not(.modern) h3,.note.danger:not(.modern) h4,.note.danger:not(.modern) h5,.note.danger:not(.modern) h6{color:#d9534f}.note.danger:not(.no-icon)::before{content:'\f056'}.note.danger:not(.no-icon):not(.modern)::before{color:#d9534f}#article-container .tabs{position:relative;margin:0 0 20px;border-right:1px solid var(--tab-border-color);border-bottom:1px solid var(--tab-border-color);border-left:1px solid var(--tab-border-color)}#article-container .tabs>.nav-tabs{display:-webkit-box;display:-moz-box;display:-webkit-flex;display:-ms-flexbox;display:box;display:flex;-webkit-box-lines:multiple;-moz-box-lines:multiple;-o-box-lines:multiple;-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap;margin:0;padding:0;background:var(--tab-botton-bg)}#article-container .tabs>.nav-tabs>.tab{margin:0;padding:0;list-style:none}@media screen and (max-width:768px){#article-container .tabs>.nav-tabs>.tab{-webkit-box-flex:1;-moz-box-flex:1;-o-box-flex:1;-ms-box-flex:1;box-flex:1;-webkit-flex-grow:1;flex-grow:1}}#article-container .tabs>.nav-tabs>.tab button{display:block;padding:8px 18px;width:100%;border-top:2px solid var(--tab-border-color);background:var(--tab-botton-bg);color:var(--tab-botton-color);line-height:2;-webkit-transition:all .4s;-moz-transition:all .4s;-o-transition:all .4s;-ms-transition:all .4s;transition:all .4s}#article-container .tabs>.nav-tabs>.tab button i{width:1.5em}#article-container .tabs>.nav-tabs>.tab.active button{border-top:2px solid #49b1f5;background:var(--tab-button-active-bg);cursor:default}#article-container .tabs>.nav-tabs>.tab:not(.active) button:hover{border-top:2px solid var(--tab-button-hover-bg);background:var(--tab-button-hover-bg)}#article-container .tabs>.tab-contents .tab-item-content{position:relative;display:none;padding:36px 24px}@media screen and (max-width:768px){#article-container .tabs>.tab-contents .tab-item-content{padding:24px 14px}}#article-container .tabs>.tab-contents .tab-item-content.active{display:block;-webkit-animation:tabshow .5s;-moz-animation:tabshow .5s;-o-animation:tabshow .5s;-ms-animation:tabshow .5s;animation:tabshow .5s}#article-container .tabs .tab-to-top{position:relative;display:block;margin:0 0 0 auto;color:#99a9bf}@-moz-keyframes tabshow{0%{-webkit-transform:translateY(15px);-moz-transform:translateY(15px);-o-transform:translateY(15px);-ms-transform:translateY(15px);transform:translateY(15px)}100%{-webkit-transform:translateY(0);-moz-transform:translateY(0);-o-transform:translateY(0);-ms-transform:translateY(0);transform:translateY(0)}}@-webkit-keyframes tabshow{0%{-webkit-transform:translateY(15px);-moz-transform:translateY(15px);-o-transform:translateY(15px);-ms-transform:translateY(15px);transform:translateY(15px)}100%{-webkit-transform:translateY(0);-moz-transform:translateY(0);-o-transform:translateY(0);-ms-transform:translateY(0);transform:translateY(0)}}@-o-keyframes tabshow{0%{-webkit-transform:translateY(15px);-moz-transform:translateY(15px);-o-transform:translateY(15px);-ms-transform:translateY(15px);transform:translateY(15px)}100%{-webkit-transform:translateY(0);-moz-transform:translateY(0);-o-transform:translateY(0);-ms-transform:translateY(0);transform:translateY(0)}}@keyframes tabshow{0%{-webkit-transform:translateY(15px);-moz-transform:translateY(15px);-o-transform:translateY(15px);-ms-transform:translateY(15px);transform:translateY(15px)}100%{-webkit-transform:translateY(0);-moz-transform:translateY(0);-o-transform:translateY(0);-ms-transform:translateY(0);transform:translateY(0)}}#article-container .timeline{margin:0 0 20px 10px;padding:14px 20px 5px;border-left:2px solid var(--timeline-color,#49b1f5)}#article-container .timeline.blue{--timeline-color:#428bca;--timeline-bg:rgba(66,139,202, 0.2)}#article-container .timeline.pink{--timeline-color:#ff69b4;--timeline-bg:rgba(255,105,180, 0.2)}#article-container .timeline.red{--timeline-color:#f00;--timeline-bg:rgba(255,0,0, 0.2)}#article-container .timeline.purple{--timeline-color:#6f42c1;--timeline-bg:rgba(111,66,193, 0.2)}#article-container .timeline.orange{--timeline-color:#ff8c00;--timeline-bg:rgba(255,140,0, 0.2)}#article-container .timeline.green{--timeline-color:#5cb85c;--timeline-bg:rgba(92,184,92, 0.2)}#article-container .timeline .timeline-item{margin:0 0 15px}#article-container .timeline .timeline-item:hover .item-circle:before{border-color:var(--timeline-color,#49b1f5)}#article-container .timeline .timeline-item.headline .timeline-item-title .item-circle>p{font-weight:600;font-size:1.2em}#article-container .timeline .timeline-item.headline .timeline-item-title .item-circle:before{left:-28px;border:4px solid var(--timeline-color,#49b1f5)}#article-container .timeline .timeline-item.headline:hover .item-circle:before{border-color:var(--pseudo-hover)}#article-container .timeline .timeline-item .timeline-item-title{position:relative}#article-container .timeline .timeline-item .item-circle:before{position:absolute;top:50%;left:-27px;width:6px;height:6px;border:3px solid var(--pseudo-hover);border-radius:50%;background:var(--card-bg);content:'';-webkit-transition:all .3s;-moz-transition:all .3s;-o-transition:all .3s;-ms-transition:all .3s;transition:all .3s;-webkit-transform:translate(0,-50%);-moz-transform:translate(0,-50%);-o-transform:translate(0,-50%);-ms-transform:translate(0,-50%);transform:translate(0,-50%)}#article-container .timeline .timeline-item .item-circle>p{margin:0 0 8px;font-weight:500}#article-container .timeline .timeline-item .timeline-item-content{position:relative;padding:12px 15px;border-radius:8px;background:var(--timeline-bg,#e4f3fd);font-size:.93em}#article-container .timeline .timeline-item .timeline-item-content>:last-child{margin-bottom:0}#article-container .timeline+.timeline{margin-top:-20px}[data-theme=dark]{--global-bg:#0d0d0d;--font-color:rgba(255,255,255,0.7);--hr-border:rgba(255,255,255,0.4);--hr-before-color:rgba(255,255,255,0.7);--search-bg:#121212;--search-input-color:rgba(255,255,255,0.7);--search-result-title:rgba(255,255,255,0.9);--preloader-bg:#0d0d0d;--preloader-color:rgba(255,255,255,0.7);--tab-border-color:#2c2c2c;--tab-botton-bg:#2c2c2c;--tab-botton-color:rgba(255,255,255,0.7);--tab-button-hover-bg:#383838;--tab-button-active-bg:#121212;--card-bg:#121212;--sidebar-bg:#121212;--btn-hover-color:#787878;--btn-color:rgba(255,255,255,0.7);--btn-bg:#1f1f1f;--text-bg-hover:#383838;--light-grey:rgba(255,255,255,0.7);--dark-grey:rgba(255,255,255,0.2);--white:rgba(255,255,255,0.9);--text-highlight-color:rgba(255,255,255,0.9);--blockquote-color:rgba(255,255,255,0.7);--blockquote-bg:#2c2c2c;--reward-pop:#2c2c2c;--toc-link-color:rgba(255,255,255,0.6);--hl-color:rgba(255,255,255,0.7);--hl-bg:#171717;--hltools-bg:#1a1a1a;--hltools-color:#90a4ae;--hlnumber-bg:#171717;--hlnumber-color:rgba(255,255,255,0.4);--hlscrollbar-bg:#1f1f1f;--hlexpand-bg:linear-gradient(180deg, rgba(23,23,23,0.6), rgba(23,23,23,0.9));--scrollbar-color:#1f1f1f;--timeline-bg:#1f1f1f}[data-theme=dark] #footer:before,[data-theme=dark] #page-header:before,[data-theme=dark] #web_bg:before{position:absolute;width:100%;height:100%;background-color:rgba(0,0,0,.7);content:''}[data-theme=dark] #article-container code{background:#2c2c2c}[data-theme=dark] #article-container pre>code{background:#171717}[data-theme=dark] #article-container figure.highlight{-webkit-box-shadow:none;box-shadow:none}[data-theme=dark] #article-container .note code{background:rgba(27,31,35,.05)}[data-theme=dark] #article-container .aplayer{filter:brightness(.8)}[data-theme=dark] #article-container kbd{border-color:#696969;background-color:#525252;color:#e2f1ff}[data-theme=dark] #page-header.nav-fixed>#nav,[data-theme=dark] #page-header.not-top-img>#nav{background:rgba(18,18,18,.8);-webkit-box-shadow:0 5px 6px -5px rgba(133,133,133,0);box-shadow:0 5px 6px -5px rgba(133,133,133,0)}[data-theme=dark] #post-comment #comment-switch{background:#2c2c2c!important}[data-theme=dark] #post-comment #comment-switch .switch-btn{filter:brightness(.8)}[data-theme=dark] .note{filter:brightness(.8)}[data-theme=dark] #article-container iframe,[data-theme=dark] .ads-wrap,[data-theme=dark] .btn-beautify,[data-theme=dark] .error-img,[data-theme=dark] .gist,[data-theme=dark] .hide-button,[data-theme=dark] .hl-label,[data-theme=dark] .post-outdate-notice{filter:brightness(.8)}[data-theme=dark] img{filter:brightness(.8)}[data-theme=dark] #aside-content .aside-list>.aside-list-item:not(:last-child){border-bottom:1px dashed rgba(255,255,255,.1)}[data-theme=dark] #gitalk-container{filter:brightness(.8)}[data-theme=dark] #gitalk-container svg{fill:rgba(255,255,255,.9)!important}[data-theme=dark] #disqusjs #dsqjs .dsqjs-no-comment,[data-theme=dark] #disqusjs #dsqjs .dsqjs-tab-active,[data-theme=dark] #disqusjs #dsqjs:focus,[data-theme=dark] #disqusjs #dsqjs:hover{color:rgba(255,255,255,.7)}[data-theme=dark] #disqusjs #dsqjs .dsqjs-order-label{background-color:#1f1f1f}[data-theme=dark] #disqusjs #dsqjs .dsqjs-post-body{color:rgba(255,255,255,.7)}[data-theme=dark] #disqusjs #dsqjs .dsqjs-post-body code,[data-theme=dark] #disqusjs #dsqjs .dsqjs-post-body pre{background:#2c2c2c}[data-theme=dark] #disqusjs #dsqjs .dsqjs-post-body blockquote{color:rgba(255,255,255,.7)}[data-theme=dark] #artitalk_main #lazy{background:#121212}[data-theme=dark] #operare_artitalk .c2{background:#121212}@media screen and (max-width:900px){[data-theme=dark] #card-toc{background:#1f1f1f}}.read-mode{--font-color:#4c4948;--readmode-light-color:#fff;--white:#4c4948;--light-grey:#4c4948;--gray:#d6dbdf;--hr-border:#d6dbdf;--hr-before-color:#b9c2c9;--highlight-bg:#f7f7f7;--exit-btn-bg:#c0c0c0;--exit-btn-color:#fff;--exit-btn-hover:#8d8d8d;--pseudo-hover:none}[data-theme=dark] .read-mode{--font-color:rgba(255,255,255,0.7);--readmode-light-color:#0d0d0d;--white:rgba(255,255,255,0.9);--light-grey:rgba(255,255,255,0.7);--gray:rgba(255,255,255,0.7);--hr-border:rgba(255,255,255,0.5);--hr-before-color:rgba(255,255,255,0.7);--highlight-bg:#171717;--exit-btn-bg:#1f1f1f;--exit-btn-color:rgba(255,255,255,0.9);--exit-btn-hover:#525252}.read-mode{background:var(--readmode-light-color)}.read-mode .exit-readmode{position:fixed;top:30px;right:30px;z-index:100;width:40px;height:40px;border-radius:8px;background:var(--exit-btn-bg);color:var(--exit-btn-color);font-size:16px;-webkit-transition:background .3s;-moz-transition:background .3s;-o-transition:background .3s;-ms-transition:background .3s;transition:background .3s}@media screen and (max-width:768px){.read-mode .exit-readmode{top:initial;bottom:30px}}.read-mode .exit-readmode:hover{background:var(--exit-btn-hover)}.read-mode #aside-content{display:none}.read-mode #page-header.post-bg{background-color:transparent;background-image:none!important}.read-mode #page-header.post-bg:before{opacity:0}.read-mode #page-header.post-bg>#post-info{text-align:center}.read-mode #post{margin:0 auto;background:0 0;-webkit-box-shadow:none;box-shadow:none}.read-mode #post:hover{-webkit-box-shadow:none;box-shadow:none}.read-mode>canvas{display:none!important}.read-mode #footer,.read-mode #nav,.read-mode #post>:not(#post-info):not(.post-content),.read-mode #rightside,.read-mode #web_bg,.read-mode .highlight-tools,.read-mode .not-top-img,.read-mode .post-outdate-notice{display:none!important}.read-mode #article-container a{color:#99a9bf}.read-mode #article-container .highlight:not(.js-file-line-container),.read-mode #article-container pre{background:var(--highlight-bg)!important}.read-mode #article-container .highlight:not(.js-file-line-container) *,.read-mode #article-container pre *{color:var(--font-color)!important}.read-mode #article-container figure.highlight{border-radius:0!important;-webkit-box-shadow:none!important;box-shadow:none!important}.read-mode #article-container figure.highlight>:not(.highlight-tools){display:block!important}.read-mode #article-container figure.highlight .line:before{color:var(--font-color)!important}.read-mode #article-container figure.highlight .hljs{background:var(--highlight-bg)!important}.read-mode #article-container h1,.read-mode #article-container h2,.read-mode #article-container h3,.read-mode #article-container h4,.read-mode #article-container h5,.read-mode #article-container h6{padding:0}.read-mode #article-container h1:before,.read-mode #article-container h2:before,.read-mode #article-container h3:before,.read-mode #article-container h4:before,.read-mode #article-container h5:before,.read-mode #article-container h6:before{content:''}.read-mode #article-container h1:hover,.read-mode #article-container h2:hover,.read-mode #article-container h3:hover,.read-mode #article-container h4:hover,.read-mode #article-container h5:hover,.read-mode #article-container h6:hover{padding:0}.read-mode #article-container li:hover:before,.read-mode #article-container ol:hover:before,.read-mode #article-container ul:hover:before{-webkit-transform:none!important;-moz-transform:none!important;-o-transform:none!important;-ms-transform:none!important;transform:none!important}.read-mode #article-container li:before,.read-mode #article-container ol:before{background:0 0!important;color:var(--font-color)!important}.read-mode #article-container ul>li:before{border-color:var(--gray)!important}.read-mode #article-container .tabs{border:2px solid var(--tab-border-color)}.read-mode #article-container .tabs>.nav-tabs{background:0 0}.read-mode #article-container .tabs>.nav-tabs>.tab{border-bottom:0}.read-mode #article-container .tabs>.nav-tabs>.tab button{border-top:none!important;background:0 0}.read-mode #article-container .tabs>.nav-tabs>.tab button:hover{background:0 0!important}.read-mode #article-container .tabs>.nav-tabs>.tab.active button{text-decoration:underline}.read-mode #article-container .tabs>.tab-contents .tab-item-content.active{-webkit-animation:none;-moz-animation:none;-o-animation:none;-ms-animation:none;animation:none}.read-mode #article-container code{color:var(--font-color)}.read-mode #article-container blockquote{border-color:var(--gray);background-color:var(--readmode-light-color)}.read-mode #article-container kbd{border:1px solid var(--gray);background-color:transparent;-webkit-box-shadow:none;box-shadow:none;color:var(--font-color)}.read-mode #article-container .hide-toggle{border:1px solid var(--gray)!important}.read-mode #article-container .btn-beautify,.read-mode #article-container .hide-button,.read-mode #article-container .hl-label{border:1px solid var(--gray)!important;background:var(--readmode-light-color)!important;color:var(--font-color)!important}.read-mode #article-container .note{border:2px solid var(--gray);border-left-color:var(--gray)!important;filter:none;background-color:var(--readmode-light-color)!important;color:var(--font-color)}.read-mode #article-container .note .note-icon,.read-mode #article-container .note:before{color:var(--font-color)}.search-dialog{position:fixed;top:10%;left:50%;z-index:1001;display:none;margin-left:-300px;padding:20px;width:600px;border-radius:8px;background:var(--search-bg)}@media screen and (max-width:768px){.search-dialog{top:0;left:0;margin:0;width:100%;height:100%;border-radius:0}}.search-dialog hr{margin:20px auto}.search-dialog .search-nav{margin:0 0 14px;color:#49b1f5;font-size:1.4em;line-height:1}.search-dialog .search-nav .search-dialog-title{margin-right:10px}.search-dialog .search-nav .search-close-button{float:right;color:#858585;-webkit-transition:color .2s ease-in-out;-moz-transition:color .2s ease-in-out;-o-transition:color .2s ease-in-out;-ms-transition:color .2s ease-in-out;transition:color .2s ease-in-out}.search-dialog .search-nav .search-close-button:hover{color:#49b1f5}#search-mask{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1000;display:none;background:rgba(0,0,0,.6)}#local-search .search-dialog .local-search-box{margin:0 auto;max-width:100%;width:100%}#local-search .search-dialog .local-search-box input{padding:5px 14px;width:100%;outline:0;border:2px solid #49b1f5;border-radius:40px;background:var(--search-bg);color:var(--search-input-color);-webkit-appearance:none}#local-search .search-dialog .search-wrap{display:none}#local-search .search-dialog .local-search__hit-item{position:relative;padding-left:24px;line-height:1.7}#local-search .search-dialog .local-search__hit-item:hover:before{border-color:var(--pseudo-hover)}#local-search .search-dialog .local-search__hit-item:before{position:absolute;top:.45em;left:0;width:.5em;height:.5em;border:3px solid #49b1f5;border-radius:.5em;background:0 0;content:'';line-height:.5em;-webkit-transition:all .2s ease-in-out;-moz-transition:all .2s ease-in-out;-o-transition:all .2s ease-in-out;-ms-transition:all .2s ease-in-out;transition:all .2s ease-in-out}#local-search .search-dialog .local-search__hit-item a{display:block;color:var(--search-result-title);font-weight:600;cursor:pointer}#local-search .search-dialog .local-search__hit-item a:hover{color:#49b1f5}#local-search .search-dialog .local-search__hit-item .search-result{margin:0 0 8px;word-break:break-word}#local-search .search-dialog .local-search__hit-item .search-keyword{color:#f47466;font-weight:700}#local-search .search-dialog .search-result-list{overflow-y:overlay;margin:0 -20px;padding:0 22px;max-height:calc(80vh - 130px)}@media screen and (max-width:768px){#local-search .search-dialog .search-result-list{padding-bottom:40px;max-height:75vh!important}} /* rebuild by neat */ \ No newline at end of file diff --git a/css/var.css b/css/var.css index b4685c0b..4bf56f7a 100644 --- a/css/var.css +++ b/css/var.css @@ -1,3 +1,3 @@ -/* build time:Sun Nov 19 2023 19:47:09 GMT+0800 (台北標準時間)*/ +/* build time:Sun Dec 10 2023 14:50:17 GMT+0800 (台北標準時間)*/ /* rebuild by neat */ \ No newline at end of file diff --git a/google0f195ecac6e90bc3.html b/google0f195ecac6e90bc3.html index 481cd09c..5d38a833 100644 --- a/google0f195ecac6e90bc3.html +++ b/google0f195ecac6e90bc3.html @@ -123,7 +123,7 @@ } } detectApple() - })(window)
google-site-verification: google0f195ecac6e90bc3.html

評論
google-site-verification: google0f195ecac6e90bc3.html

評論
\ No newline at end of file +}
\ No newline at end of file diff --git a/images/pubg/pro.jpg b/images/pubg/pro.jpg new file mode 100644 index 0000000000000000000000000000000000000000..c799a20bc7d96a84bbbe87caf169946e2229e01c GIT binary patch literal 196225 zcmbTei9eKG_&|FnX;y_B-zJ|QrTj%@20XP#w3Pp zGnF*SzK$(pAG??t%<6mh`FwxhKj3#5Ua$MU=bYlru;P2r>N5sX%j~tRdCMkJLT2AVul-yZ)`Lh?*FB%&=3;e(D3;qA=VD~F< zNMui?u;Ly8IY97`z@9?_yWapQa0Y^V1i%LTe@#GekI-Lxg+)YnM*)%lz0N&hYFg#$ z;p(BDYw>fo%{%+3#b}$wFripOsitGpM$0lK*U{5Py?Nf#S1aK#2I6kHl7J7Z`GtTh zIEU0!<|_C-6RZ|Ld(E@Df3O828C&sfNUiKhUUI}-F0FPxGO;u9B}*mj#+5VDM6vI3 zSH39O=b9P;Erj8Q& zS_sHr{3$8d}-M(kjwMZL=+KTG?qo zZL>eNmh@`d){;|dn-42B&$rc#dOCP}=lU{&E;^_(NC(=;t_rSqWAmFLj;qbqTCfP^ z8hYmrUDEizZ%jzT^VgD(kI(9=*DsI?0#?i3vf`Sn+7#dKt;rhc32Kt>!tdZYu=F;b z6=f@cb1qrze&J4t%T8-8@$^aQceRn9w{hCjUI#ynkR@pT7r>6|Ua6)j2Xz;_Q6jw%RVB_zJ#6>J|Hjtsv!3*sudO(BBW@ z32m#Npi*ov!W1(2+ZOaH-<3rCjoSXQtwVatgMV(`{yLP_QDXMdv(KXAr>A?anFkKi zF=`F6)mKzG^>4wsioY^oo}L~`$6#_E8iP929647cq1^7jb z+Qv(n>m1wdR#Y>67qDcJt%D=2sJc2tn^ukt!YNp%z-z%*`b92=8rvQX?_@sKBqcss zAibU_EZ^+@i9X5CL%MB5uQfo6N$UJWt_R1TuD#Ixy#VF2h}WMQwiNU?co zeAU3qEMg$T#osBh_~)j~{h>~*@V+^yAB)sY%2tx8Cm!PXv!dVgbCF&f30qdPn2>3x z59&0Jx+Ak7t$16bms8BWZE#*pezu0+UXOkiLCS9PR`}MYp-w1L(SZEO{b{2G;ulgf z_|Y|^HRWv9yA%%%4T+R%u_Cs>$ns0lo?pG+eepb~br zJD`H8sZ7OHXuC`?6pKBDwj^rokgM6H8@yfM9@l1;)FUIa02RNVV1|I1!#vb2Qr&;# zDtNl5jhfk8j2e&j$t!&{y>{C@UL;P`OljYcd$O$c;nW2~yVwafm7zKhH{$N0L#xq7 zp=!M>%%l&g#t;X`plsRH)t4@MeMqNalmou47J8dwi0KR61>$#sJK-3O`c)!g6WyO} zXvv@^ayh;HSklQl%ul{62mM1|ae7f3dOz|82z2fsox-5ZKwqM0WgD1YCu$CyxC;pK zySdf#3J#HLD$WCoEY+}?NQzr#UC$J^#76GhPY?({`%i1!(@?S)PU|dE@K7_qDcL4o zrgr$Qf|7=iV^OSRk*c0n;-R6GR^n-9rfd;sF`O)pD>rYIzg6PuA*=H5E4i~z z@8*=cG2s2XfO43>6}xfH1+hiSz&m|IUFSXjy`E??Y`DxiJc`QTS}{o!nZL#t`B&!M zfAKK0yTC=e#tB};#u|ChP-#;+GH{hugSyRB&5pqO&(%N;!qGBw=!-viXqFp;Hru~N zdxxy<<_BPhA~5Y}zip&d`+y>1fgK*E`N5{DjB$!y^=(u7LUvlQ2Bb{`(oyUlmz^v6 z%HghKtLIIpzSJWXKM$)PwGdD1IGbaka!anwVs& z9^70dka2-d_iP`a_#Lk6$)O+=hK5dskEZuyS3K0SVP>z|qQ^&-8F(2#R7Jghd`zkpIRUm4k)pi-6z zBZ;J#9aef(^CK4mYLkbOsl0}gnUcJm&0#GwZ&Qm@NUD-(eC)H^A_}6S7DfONC3wYd zbgZu%#`fErF_+QVH9AQBl52;y^O6d*X83%!L}ryZJhHKKQte8SuqZJzbG5lEK>+=e zQMQ6vvXVTcSSdTLP1XWrl$_k*BRM4xp219IO^qb7Ab`O60-~kDoCbZ1SrNN1(^7{| z8Vhec?yozR7+L-uCo(Zug41d;HB(pcyket%W9Z`*(60XY07-GrmWP0FjLSAt0;<$) z{bG%kMdH%F3Z>*VOpAh{imA_q{rz}?W^NfK&`#ms#7^5_(Xj`s*NfydoUE(h>hkIe z#y{N^ycVU<`2iK8X7|(;j4X;FKhl1BK;mH5DP{s1LT~OX9ReIh|A|~fA9xJ_LK46g zaTqiEqbr~8*0LZJD{gFj&Gk%Io07t14RwjSK8^&7BzgL@2BawMiJY}XT(+qNE(~V| zGft7eU}5VkE+_kHKk4$Q$&((CKp_#}r~)E&K@YZb;E<4r!94K7WAp;?4g2~=X0Wva}byjh_JL0vynBQ%}ePJGudpTl4#TRsa38>U*9yXO7@{PaEN-z?T^Sojvl#*hd;`N4OzKV_Fd&P<-%clLf z=J~_;ikVy&eqftFGWiK9CeXX>64=M;4xx)x@I9jd5g`#dPX$GA{fo}HGwaw)|EoUu>}gNkd!itHQ_`T;W*kj=hgEn!h4 z)aBGq;fP@dfMiI~ZKcx^LM1L_rWTckNdcpCFq)T05tqQav9W=4{Ex|};+MrQA38N+ zks$N~0&^)}+yz9VAp!EPf=bn_4gpTWL+IN5vtKSK=10%p|f!Be3S1;zj@f ze&hhF1_o8;vXIeJ5xGNM*~#kX1T;=VqC_DO04DUTST@Dx5|NymT16)sm`WH4#fgd^ zR?h}bi^u|kf|mi2C_qj`_L+FE=?9Ca)~`~`u80cAN|*{7y*jLvy(MG4VTYCZ{7gU= z5D|qzvQvyju1J8Px`a3&Ybt9jBzby|X?hf>n}RmIOEr%*d!EP&oK}KdmQ8!=+0XFX z1+qFen;gFiUNPEt>w}zt5^!1#0^;?V$Sc7;=gD?rXGFz~MMMTbeJL>$@XJKkkqpiY z$IN~!4OM4xHEWcc2>@>O{#xq6B-@VW(veYh<3fl`JYNA}B8+AZVmm zyui_|qwO@w%85KF(~vy}NilAipkOk4d@hC(uig_5@sJ)aPMnu!vc|Tz(5fM4L6LeXN zC-P5SN(<{337Unksl0!0(OC^pEjm#5881 z7oP!93Z_D_5K)QjPL2k%64QdJXPgTk_)Y4NHqfA0M##5pZ z$A0d}Os_~j1qT2i<`E&iu3s86`zY;G8=;^*GZIjfli2H5u^57SjyB&EQ!6$$lDI08 z4Va3m^z$OVb7B%VTw3N0g=xrtqoTw?Q5B!o>Skcdk$V_k1TMCWr^;n*XYJ6Ya1TC5 zfkOxwsN^>%BCCd;hvqdO0WSy|Nu1QnDj(Y>xw143Z?{EV7CHVrN>nHgTgWfz?4&*7 zr@o=%yNHiofhY$bH#1kHkREaO45KjkdD7EJE$EHO9jj@iHK-?5~C7^I;m@P&PWP{0&&<<4LgORM-Q9x8E^%DR2)>>xD98YyAd>6>z z|C992C`uF%GL<-d32n)5B~z9sA2JMxnVq|U0pGmE8W0y3iW0b_RYzcG4>tpPahnAWp3b4pWjEsc9IbPqICmA#*<(_N|4XO#cYXk}!fJo&3N+S2L z4KpWQJVA?L)T$1cN=W4L^nN@xOkis)@UpohEX0%ewAjl6fKU+tvE*RO9`f-?CK%Rs zDw}k5hI)+UD<=dZ9uTSy`VgpnMp}7pF@osTwfyH&6c`qCMdH2LifvrwpRu@mLZ>A` z)q`TyS{0pAp-$Rn03nq4_PE+;2tbf94lZAjNp(wy& z)noZ;`dl!lV2rw5HpiDr0>=@R6}&Rk$rM9OBQbd9$%aspMWmhfk3Z2q)+PP25FjdO z9G6#6x9(E6KK9FUWOyQ$RY&jsJoO&bML;MH52tcz*-Z3+bYm-WA1#j?0kTlWtO7H*sFlb1R=UHD&1>s=?aPVj+ zclE`qXX3zN2~#r-e{;6~vI7tQw!5Juazz(=h#$1<7AtE6YM|0$v+y#UJaJffu$Fth z#CR=ohIR+@DsVCihyp}4!mSFIX)J2)+QYD0t<^apO1HpKA%d5c;Z*eXVCF8M{)kJ} zTf_Qp>D3qR#lPaaJPH^Tk_99rAi3~$EQ)=!yW-byTg;JlkAYeAMPfw!2U%IL2VZ~G zYka4nV#1QWezCeo$u3a2vkNR*b&sZl?gotKh}7bh2lpS=&{@s=PQfA>5`$0J>dB$AOd% zlsUKl>AOE(6H>$zW(q%}qk$2QX8nYDzQK98RSUmhM_ce20FI%c%VDv@8^#E&Kj;s% z8j=42pe_i-S=N#M3q)H)TB&OMWGC_)DisSBtmdh$j?DKWQ3A52DMJ(d*zo28jMD>l zfq5r&QI~T{rfU~S{BTnQ)G&$Tb*Rp5bm~K*!4m(?jS!8`0gWz=3vdXBG?!=&I#fVF z@g339X=$s$jy$c?d$`K{^`H4de?`W<1;iadt z00d&DkvhB!7>D5dmwhNEvo1DujIQP#Y61GhB+eKdTU2f47Y9B;((u_?|H!C*MBqEn zyK8wi{oH60tJGy092`(A9I4#}^sv1JYnH#P^68tS2FDby8-s)crZC@BCPqiG+D6QqTdbD?#iC9Uans*0BM@<=&ybosemjaAR?h z1bIhq4v7%43v>+gga;ckSN!-vJCtEmK4r5(rhuvS9}ooynpoj6&9h3W5xrZHD6#CF zu;q<>Keazx5PDX^?`N8Hp}N^;ybf&G6joK0x9m_q^JkbAyFkG%Aimru8w)@{G2yp& z0ZPP(uGC9*Q>ALR4m21{tQF(9BlFg>pt}$_r`F5!z<=ekqSsw!su!DiBuON^cNZ|? zYGZe{f9P+UMuGG~!VP1bw38oc*lC^OdB8q}JZhndIbkZ(zX#H3i_w=g5QPAsjEOZvD1VU6)MI|OLf^_!A( zo`4gU(EPw7FO8zbfB&-!*l~QZZ`hGyUnV3-y$7Hj(l%drTzUb}6v-P__cxVhkS!~_ zO{(yjsWa7f2&lf%AGSQT-Il>2?K+_rypUoP3ZqfIpj|JGm`CRkJ6HH`(BDZpRkpJ4 zKzOE=D&l$VOW}<#vvmq=Ol%hZsr$&K{tn43GKvDbdZ7(RDbi7nvU%yC}d25Dlu+VmG+hWG1}1q^0Y0V!};wYyR11Fa{EUl!TBhd_oWG z0s|9;UW$rcl;%Z({(2nu*E%tAYni*wqLe58WhC?jlB&JVU)grzIORI#M9OGxih1`i zbm14cD&?k61pr`=E%hzGZUcK}GK|>5*sf$`t0U1Hs8gf{UR@hewRt0K#0Vq>@;DN6 z%qzNmU@Wd_cENMz`hh%SP&NR_b^fPK2O?|BkmhC8{pbVxJXNn9bz_0I%ur#;bYa9y zpBeqpS5FqnpXXKFGv3zLQZIHSRF-|LE-F?G!R}P6@=n7rwyamh|h-@ zyiWgaXhziz(lxJ*eSKqyM^ij992 z8!j-5db5o!VgwVy95&Y;A-!f`y!G{A{z(@6fOsq*Ayi~Brn-c$56|aUJXm3^p*#87 z)4RY`UP~wc2y08{DTv3tgk8WY(q^WqJCn8E7=gdqgYVgf$|9Y-5;@Uhe9Kv8bNBqY zD$sCBJW*y>QpIB4+%d=-@yA3IT0t?A4GruC0Q3X`vT5CYs5eu5^bm(K&}_I}N-OJZ zncM~TJvJy+Tr_N_d*xPK{!h>-8G_Gcs*Xn1qDUI0t)ARfI#y|cbbk|i8mTCC7evgS zqxz%<_z4;^0lt1R`}h61Wu)74$_DzuD!1Qjm;=p0R?32Q#ngwvtoxLuXru4T2<#i- z4iPg=3QxTHV^$#Y8jJjq89sWDvkQ>6n_Uv=fsBV-`ft?nWnSvYj{h_3(~_?QWK+!G zJ^ZH}+Q;_#RCp@&H(Z_-5)JyDs)wiuF8+n=A7WgZp;XkKAED4R@}ar~UZ(0VE~gCJ zx)8`gU){=$pk|(rk_7EJJ$mio_gUxkXYny4U&c9TIfGki_5Hme&D7`><0a|F# z$(zpQ^87DNlJ?G2c8~C%ak23rA)9jW)^RE0wwKYyB^I!TCxrna_^Z&95J*5^*Cfn0&aDK-uaZI)d> zFj3jX)3`gmQR6-MYp@Ie1dT)`(urR%Un4mTFMrG+bL62rEex8%SNUSL4RvQ=({}>? zg8Ye*e6aU;s*EI(iM07@n2LWIKa?diz6;#C#}c0PIrPWns4dO2wHI(=Daeef6OIuR z>$!uI-ah^jGOr$UQ0vR5R8w|h|5!u_Th)W6PcyvT-S4-x>H8?`lmQCGtG)0V0AP?m z7!DbkMO85-IMLO)!`DwCp$U9>N_p{?SQ$U)chECX6-{AYA?xr$o}yQIQvD||iOS}3 zXfiUOpY9+ja}%Ey2?D^u;Ptnhm})M*?fs=4wv<(*l_Gh35KPDvm)F?vcWmk_WJAxN zKxdRGO>GUs9d}(`@myH&Y23pgcOz)x_G z;jcBX|3cl|Jo^o-T}jAmF-Wh8)P;z#tg z_BVw1%$kpXq<h!F0~-u3~uANBbp=bVheycHZV z9O)MQyZkbc1_<6LaQVIq#8T9KgWTTqjgGa>G1M4bxXXpR;AH;D2u!xe4CfMhO&(+} zFdJE)xafHq=qYuc|0v3j3}*SJkTmK#)^E#zy|F$BrYS6H<_@;~Bfn#8hxU2ntIz-d zXzEI*jv}!qPUPg)>k>DSH)P=T)B5S*P6ng^1~n?I5rmYe9?y&xHf&-O;^pQQXxJsA z(bl%8UrSR~NCWSh3Y^x!uAycSixH|$jlJXJ!%23+Eb2_aSJZPR_9^QJxH=gHmVnsG z3n*}j$gkkL>ZO*J%|vuEa*JA3M^xH4VGJT=&)zN)A}cyS23M5{ZDiG=Rxi1DNxKyD z@aP|555Wmr1glI;2K-p@pC?^K_-pH>w&Gz;x{>?71%m82ENEnE!CtS7G%q86SwJNZ z)m?Q{37xRpQ0-LvvW%MB#N-Z%gGM*5V7-{rU9rNJUgJ|V5@(Pm$t;tYPL8n5cfOuu zRFr_I$PnJjOP}yer;h*fWBO+nwr?2*kTFt`wGa!g%1+TbpLXxY>#j|f>NBl#-!>>?b?2zmo-_wAgkwi9IQMhcpO_!yNHMdDD27{_Htj=#4!wL}# zu+B8M#SWQDM1ew^;L~@?#oXL}xDR(1k||@D_t@|kbAJB! zCIde*?8rC*_y~mAunSz-!x%+qE<5!jF-wtNoIs#4fcmWz3jayMT^g zx1?xX)Sn!ultAzq{zT}ksvjO-3a%gb&vi46Tx_Jgt;@W5r zaSY6BWZf5Iah3nXg`&k?PdVG9FE+0SQm=*3f@_;NDm(tmk7Z9=F{DrMZ6ReQJnYs4Gn&s-ox`c=)bE}M9-~*Fnz@fHJJZ-ou3o4?ZS9$+f z{`nB7b%YcVV_s+}CPkYvu-yNzu>>IWL=RQ&l-u66(wMDWUfMnTa0^!^9`$GDpDk_w z1`99))EtrrN`0txw!ZQ9VtC{^=Vn)MY=I1IR!3?N^Hig*!^T|S6x}eLSwN#@cGN`* z|M4TQfc?!$F(x)vCa|#FJJO|IfrY7^JO9ca64lze6pe;L{AqK7!I3Wvy~J!rgX`?8 z7B-sZ1OZEHXF z78*;MG8ztl#ik~Qk?cCYfg@XaC0j>~TX-}!bvAeY_)?0;T*<#t8W>qsPJj8Y_#VVK z{5$<5STaH4Qzn=}^rjE_nA_2Ism03%(%ePYFJC8@#R0-)4Qnud(ypc+OcE&}TCg5D ze)@@SW_?6&hQY{-pTbHzQSVR^6Mr%ip z^9eg*C+D~y+LkvK=@$)-RV>_yQ8h71u80z3{8bLfOPq#i2RiL7*q?Zg(w@S23reGI zm4_cdLqp$(cbhY1qFEi%Gfe#Fdc!@(tRfQotD=9>LHl9M4pjG1^v?~)pWv(Q5{4_i|-l@9e9xR>`T%#Km{Yyw+1n@Sf#RM zs3Q_iGc*^&^Q<=E8k;J_vX-icp zvj;sOn!=CWl1V{UVk>yw8|XZizF{L1+SWvU*4o!uR+oFeTea;0M=WGjyHIha(~tKj zlBj#ft{dUs+kmT%aY`fRUG{VZ^QTq~z37JU@SL1sHF}}lo5A(gH1bP+8)^^EQTQ z1L0`Rxg~~lU1u1MzolZKBBfPHv#A;;svas$yepf*C(HVJ&JT}t7D^nZj`j5Qx2=X8 zClJD%!-2idvhAQ6OOCZ$=qT8GXP$SQ$pWbWF@B(8bdQ_A^cvY_@40*fgPgE~VuZm( zHrk7A^_$w^Hb4izc69ys#^Is4fuKu-U&}ssTcfW!SQu1x+xSk`r?upXKm;TNAltf4 z%?2kTRG19S8l5y?->taxNZ}HkH>{6PtYlj3?Pwz%)*9^q>)-2BU-l9l8!)?(^!-jH zSy?{VJCZ1zz>HLZR(XRZB>&ka!@{FNe;!fLy<;|1D{Xlo63hwgiv8t3C*FA_%f9~i zHD%aP)-<6Q0qawCTxT#fFEtdDlR{ft=jj1avdw}UaGND>m~~pQ68HzF)|W*e&1rZU zgmCXHxbPVO#0n>iY}0Ydu)dnSF+IIJ?x>!kl!GQc?gQ-0v5{ z(UwrG>}Xq)Nc?_It*{lRT)7^8qvW7W@=FKc8K?6^xjhaM?@Fk!B|Jx9>!Pu5VtRst z)#>%=bN7JD|H78o=$kIotGUtL|4U8{+0nE6MsS5SF2Z9pKRgNmwsSPEAsmO4?H3Sp z!^EuuOXs?mO;|C5NbI#-w_YwHvvGg|=4XArLvqTFt#X8TV?V~n#p~x4bc*cI1nS7l zPVDzjvfB-s+uSTVcc%#KtQBD&i)+kDqb-MUhBp_M?@jiIWWf*@+U)B}n34>BV*-YD zu~;dordT;CEx#!z@27S8T|#X&!VOgL^^1sgma4%Ua9$@bj{lq(AXau+MCd~goOFrl zeXzprPJ77Yp|y_#0*k@r3k^*bhL8TtKAz%*OG%^9dmX=%&~JK{yhD+Pa32K?))FJP z&s0sblH(DQI0U$#?DlY_A*zPmRe;yFamtZ1iffBYl^kL6Oy1#qO47YyZXjxGq*SV~ zS2G{DmG6c5`g#8cdZ4CWJZUyqAFi(KIHX~tFy!*0IbdzUeR!6oq8l!AjWQpBO$$^S z>m3vUgp0WcgE@qfs==2lvra^e0a!oK7zTjuI<{o1#gLeksUV{xvZdL4%d@gQ4W zYX4ro*U$Kc3?(pidH^GJr-P=9iMP!awb{dQ4s+E+oRa9 z!rQK3@2<`32Du?xLl`UUP*2`CT$e!@+P>opPhZs4{d6Gb?jK?*jBTr6tq92qKSq!b zEwJ4AF|L+(kP&8SO19|xBRNh;hyEPGQ8@_|-Gd6-#(HL0=NR1hvLUWj3>=RuwOBe44guN=( zFfy1=M4N}AF}9zk{(uSRDo5z7s~qSZX4tm8L7sRk^!Ifi1z)}|C^S5Nk!|&22KPtR ziUazxgDy-r2lTz48f}enH3E*r<=Rp2Q<$Z+?qh$zn*oLt4Z36c#9crwH@an{9aH~p zwC9^Hx4~uD2w>y}F`N2IA{7yMfRL{Wc^4bUiTMUF4?iwTQYu#P$^YutGCieh%U&y0-9*D zc0$B2k@v|uZP8TLRAY4;iUm2DHS| zBqf^z9DZhM8Lea(j}RtwI$EcbC2?{D90E2}6L06{rBIu3pfYJ9I0K_|T0zOPxIE$> z9=D~5V{Y`Nk&{4FC1ovF$K1P&|E;jDvX2Fsk{YOW9@Vt1%VIFYxHW?QFDjA`=X{dJ50pHd0u?QE+0ietN{FqAwXnO`zi>jb=$gHpT$RqUV|lJsVgGOrYsHD(H2P#O%xChgc^||8 zYHqCzG9I*(2z@y^lp#n4rEJ4oM;?FPxbfFn4y32;;DA;}8c4{Oup zZVEoo4fXi(PKvzpvgJqD8{w0rGR77opAQMmv6E6t07!E)n|ZIfE&syfkfia1 z>3fx1H{fB#NrO1=oMM+`Q__7Py&LhXNbINvZ=vd(E%wC@`L3%zMB5G4VA; zYTrC3@`hRCqqgbSf`i$H2?-r@r#&FsqlXzcpdqyJALQHMb8^b|6}QLoefJ+(WCp9g zDgU-l`S#l}$DLZ$VsEBPsiHq6Y;-5yI&0C^(vKnrnCD8@OdLX^xO3$HXD*Tf;$QlkE^TPB-fH zA{Aa>6_5Xw)UBTFo0P>1c~>b)HZ4}0DOQHrNvS4CH>8#P-ASOkm-9PxBG3=)2)(SIvUa%W?P*M4DP@t>C3r?YV8oDfolvA?3aSF)MZH{=zd;2JkraxT> zIdkG2spq1yv$^$Y(-Pe>>qcx5KYatON1EpccH0VyUJ1M#=O~+lTMS;-e0k(O;r(;9 zx$&{2qadD~wM$SW^HMTh%dJyVdKb8kEhb)_Qie^}*b<7|j-#V!0b#SQ;w(r;n6VawSSetM2$j4bF`a$sp)CKgLW-A(6p2D)~RzCYx0TSOz zU%sL~{c+@`m3f^5XZ;ELnAPTH)-=NQ>^${l-Z{;9%YfMyDd@GTF1p%%@`F*tI-{KJ z_7xc+RR#tD&Q}N(Hyvq<{cx;vgiFEbiSbp$O211+r_Uv=Q3oatHpk#sqMk6|*Je=& zFel96He}sP(F}+bUX@8D8FS4$mnkPQ#@VEDrcAyLcgayXE@Hwp*}LMamfA9hr_0Y? zWBJELhR{0?A78vJCv$~Ut7bRvwy&DR1@zV7T&oTxWj7xG zaNjzE5f*e|agq!hdgNZR`ZkC4fYKakSDL2=yKpzY^>z&+0$qf9z!UquKYVA=u@05b zu=-~c6?9npZr;-u$iSxxx3(K@^R$1C(Zgk=UfSM-xyFG7SlgwI@KHUK_T*r~P{I(w zMa3t0WUwtsCFb1Qz_DH$nab`?>LhJ6C}qMWm9Mc!0>b8$P2c~`Xg-h4BJZZP&ahtr*pmRy5%<-8J z0XABCY$@!4Wu&1}y!DyD1tJ+r<2`OIdyG3y$!ZSxHdJqz9=+cc48YZ=Zk)>5!Lc)l zGB3AIa(97F#|_PARl_-%BSYN@(heogh=~boBmOD7H!|G4HPZRk%bNyyZ2iBjZ{zOY zqpqxn?f*ylSe^~q#z!rK{^D@q@y%X`*5f!yskr{$VyT1t11f*J)}DJ;`EAV(mi5RZ zcbZY~whDHA|4lVr=9d^lvV6XE{v_;+YZ4mf{h+o4*`W!Ts`YTtF( zb)7F3Y8RW2v}2EXF+#NCelGeyBL4I9*{v)&*K9W}WN=@z;`vM6b|JVJq2;+R^)UzA zvlAcmj<(@xI7vdlOwG5)dh2JNZhh~lRYez9b*%xh)n4-do34R;335^3TLTDPaWyT#n-Do$HME`VjYNCrj*!ABwlJ!ZY%GsW6f|a z(Q!;V(j$|+xZQxv8yFfR_sq=(YR)Sk?DEPa-?CP^2BQj=WnywSwU)u){o(%0W9{TyyYo>|GTuQk;+QsV+Nl{ENy&)p&iX} z`&M#x4BYn*U19kJSMIaDFi#rc4Z%~nwW+X)fwmYgO*QqtPp30>W+o;p=cR~ulyQ;v ztxvrQyUFm&TVjV-d3M5mVd$qzGrff>GY6&#?U$vT zb&B?mE=hH01PqH0sH*-bgbWS-Sel!iNf<3HW>ojBEZO~VI;tP=qF!y8vJCD#=Gf7i z97CsTiknpz45(qO@~>fR>wR#Q%?pm7@RI7b)XTkfq-npfgRU7R=l%&QJg+;}$B)|J z7p}-0T3?#vlDo-HFna1yeLF(6&rIJ-&Ukaq_3tmXL$t_6D|D}~v*fbivFv!lLS%wM zW{cWTO{~1w8=lpS;ngFSDk;N!%#WnnlYtkml{*xxCBxtn9GCV%|K){cWaCw7I4Ruf z5}ouHY{UVVYk<08@Y1Ov6~7dzrE{;g#uZUTkqYqI;*uhMkIs~w?NePbY#-Q?w)?pQ z7cI5$9v(`#rsev~a@Bjg!JeIrLZ2T#dqLv?qJ1QyTQd{QRHXSIV=Hc=lPl&`FS@n< z^U>+xP~xUixX0UHys~A-N)OFxN~s+j6CJoH-5-}Q1x89=1t&6BWG?(>e0lIIoF`^= z&|uZ#7VftP;+t(+tM4ib`(f)SrR51aCE!tnSlnw!&1Q~}l<|LyIks$Tr@@_1tV zB2~V7I;cEBT0h8_?L9i&&FHqF6NNjK`-bxm2wQpe263(44sRaU@M(SqwdJaQqjWCY z?4{T!97ItL+oo+^b%8gStS^x+MIrUu&tHycT%N2 zPcJ-JzP9xcVHmx{)3Sonq1u0!_!j&+paL5+>}n22VS1<7GU#cIr9ue!n8K_w(&BM^lh({_fm;%V=#ou>L<2@wa7=whzj&$4fo+j@#lDwmqy z-`&(f-#~dW(8c_doB1b#9tRnZTu=y@b8U+c)~uCNHx4(5;|w50N(>U{s|&hECgy)% z+?=1h`!*|+aCem9@{zdjMavDMb}z1-W73KAYd>YV%^v3;-5=;UHJ&(;dos1OT>y$+MW3VV?kFS28h@eB#7JYT6zY0V*m)FYOQr>ThI0A> z#DYeh^87l~oq9Ahp|HoVnf7*vsdPl>+QZ2^FXG)=4olW#YlpL%y7ucz1w{^l>^$04 z^t~?dytId6FegX%z}h@s!!|rDyy3(r&3jm@^Ia+la1$|v zWB5eKdA}0k`o6Lk<2=NTbdRG_FrTUU@&~hUh5hvx!VjEX3*;TFto^-pI`kJ34#ctrK5Xyf16f)9=Mvw|44NwayLN3sdrf-c7KW1ZJCm zY7@p_A~{1AjdR>gyZfcEDWU)9{)#H|)w!-ppNOE*!HoS4IfErW8DCPhCZu#}tr*>k zuu{9y=CU#!H))IQrkU1EG^RiWgD=zSiL0IW?NSgmmo{5iS(~IY9SMzIN4KpKM(~*v z%YhM(+wk7CO2eDE$flhT&PhFIhsEB8 zb@`R7>5R1DBO^RilKf-NMcKURZ@r;^NF>(LSKc)z=a=qKucgns;iAz%ceku`oFm2c z)9)@vcZ=%|E%w*XPSqmyvi~)<4ZJ%)M;4cNvgk5MtbF?Dfsaz|UI*IxRBP9e5IMro za`jHLN@5;2Yq*&0%OXbVCdC%cWsXW+?&PA|HTyZj6 zW6@)vrG4b3RyQt%*?uv{-A>jeMI%U)KuFbqbxebWD5(qX?YQO)<#V6rRWzH%{`p75 zc%~ipZ9;BDZKmpFN#0Vo4LmHY@?7!@_IS)9sUj5p9woi0TEQ;xO4-Og4({fKrdC?LV3qrV@D-gGBi%J9u&X z3_p%T`GJD=@dml%As(Erx}f@*m^s3->PN;@E^u4sNck7pM-x>#JDMxkJA=6>af7`+ zS)10|?U{0N@nHqK0Q1-eRZ+W-cWkm5{fnxyjZH=2XALmQ$G)>Udf|CV?q`pV$KNZ+ zC~2;12q_|{EnHhf4iGzOi_-YNJ}z@T3pl0FH+=IglIWD7LwTX6rTOfDaYvzo`iB^( zi+>-7OjTp4+V!;VoTYw>ydHyRSq*#&mrm&NN7}hDu%FdJb^*z+{-L(-YA;pR?!W1* z7jgUN=wMs4RiTS2!>VzLkK2TP;A?Xi7def5e@b9|WK(10-b}^e2-362{-H1#!iEk% z<~QE_=c2&KNNd7*m-ORN7(FlpsYaj@e`E7VSNUStMJw9RKw>9&9%2}3z_*!5s>_Xr zBCrgrjA;c=`t7>yYR@k(GHBjih-2+Fy!HiR;4-*NM;=)UZX#t8tAAS+?U1s#i2U4Y zTybjtuX)>$CSOI#_Z5SOy597%Ggo+6?Uhit92axwQn`Php~lQE;JGuu*MaaLHesT# zH7@ta_1YSWN=|QlSH_*@JAZqluW;c1Z9&1qZddq@+}s|vcH(jXcfE|`A2LDveW&}q zci1if?o=oZA3X)P`9g>OL)p}wbm4H+;>T`ASG3-wq3x0QK(@+eHx0@VW^Eku*|GNx zEg}9Bt!M{s>ilSzvS&X2p}V^meVdpV>L;=Zkk%)o@57bMs!G8Hs;sArRl zC{z_Dx3=FY}Cyo3H@?*8Hv67CMTAJ@(w;aWpfGAUp{2l1^? z&27W&2{d#Y6*tC`8ROeP{V1I*GTdCec6)?aI9-b}rw`84Z!cE&4pZ`dEto^@AJxA* zQ)~EE%#OMhz9;LL-7;36;p|7&Tj#;sk;hwtYJX3z1e7(u0iA*F#Qpm#9(|*0sKlG- zzcxZB+C(e%*vp7Yuj%}F$~l)$zGg48dJv+UyH@5Z!>;%oQ3vr`NK)7ERh(Wi!nK9O@c2Xw zEyHaQZo(%1af?hfA9}dHazA7=*$k)9>*QFkb~!%##7K~vLa+`w*;yNBbHDjkTbXa7 zAIA2?*60MSKL3X2&=J2!nktzFk5~0-hhB2*H|;z!q^HEn@z$KTnZLu6;2H>%fS;peQb$|+$S`HB z_9Q(0rATOH?1oWmWo&bFm$u4;X2*RjXp3%vgF zZj66)uci6+>30i@-qb*s4WEV;+ljG!N3V3bevQbyUIQyV(hdEt8^jyuY3ixT6qlEuF^B8zSdxR&2DsDp>^FIxUa8Z+7(M{t>05gy|8oPXnPdMY8$G+f;4BBf2Nl zWI5K8A*@&+DqqDKHj}&S7MGD;BG+5ztT}wW+#@sMgvLypbMX5C7iR9gN~C6+XYr$1 z6$x@!`*F1;A5Y@Rk3j6JecxuAt|P+zFd1$5u7!)L)ddB9V_Mm9O}70p|A;^9NZsco zxiQ!JkCzm#@wO@hUiJ^_(EOv@DHo`xTziIJ<~5S6Zl39-G)80C8r74iM3z^lAh;iF zMf8xGsGNfTi#mr#OJC%R;?7$9e0x{&ZE*F2Yjgs|+)l;U`TdY+dxT}c;DG|N#J_}& ziN>n2&8D2Cm8C~2$of$G+K-CzRlSGQ?2BNoL)E9?()$)xXY=UbkqEzz;b77|)Ym@J zRo0i^B|ds-L!Hm{%Pr90dk0SbdF8V0U@Fx65_9(UY7WBXkUu_Q(2+^g0}y385? zM4pPW_*k$1L)cq~we@He->Kr*)uPR%N-On=Q>8{EOU3+V0L#;>YJ2piKnG#779{%_NbnF&I+;u zSo+U~v6rq28Gt8WL;aqkToQSd@osblvM_Rm&Ajz>5i{GJr7Sc^3750NQP9!9*4?xj`+o$O-@?^8Nt2 z74m)42oRdN`H)k2#?o3H576*NoNY}Oj{tz)yCpIdj8OxR)S7#!!@+;?-eURUFU5I zyOCr$-~@2jFXek<=HGf5n?Qgk~(JN6Ez%ZAm`t zny(b_^rLx(-sQ!{>Cp`EL~N1SqxpIG(QS?fcIv1$`{`q1N##Hppe_`;yx*1V_1N3H z0st?!GNOGvZyzX*T`vK&_7X$x+}hA(xh$Mg?r2{VNk855&j9v!>d^ZD}-Q3;rw}|=j^K4`yA9E1^@9NIs zRNe6se@ks<${h)H!599-XrJ1*#?9MIN`R%vMBFy2A^GQ!0h&R^sX)*xU)MQM9d0M@eDLV4?mAMp`tSUC1H8Xj-#E&@up zJxh9fa{+p^!d_hP!Hda3ls0GId$`(os{vqceBV|R^S%U_FxRJ9)UxEnoDGa1 zKM|Fj{s6gNhfwd@!-K2{fbP`OnE&?tfE822$(CYS>FMw37-Xx~B1dD5B^Vv=$w|EH z#^%KYD?lK;GsfS4rG&}KKdk0n5@698E!a?P0q?WI#KH-i5_(Uffi|3}`ZGgxSA#)X z*vJgEV+`l}x~=jT%e)#heL?`t<@>1Sd+WT;?83oH{IVHp7HV9?%7pIJ*h`xpWT`ja zF?CRrfAJZaP0FgID&p7Ld!y)sgPgz|2^F)?8h++Z65zifqDHk#px=dx3XVxRK`$)8O)w!wKLtesqh{_OzQ{s%_IebVYkNKGZSib4l9qm<) z!4o&9rHEm!?S$7g6DmEM%sI9h)jEG_N`95-SN_tieXCqIk@xg$$k##1TuzqKX z-o}i)93*m?n_EZCKOCyU;fh$0QFH5O%qF@b!uV$Lnw96QpF)E$?Cv zUmh@_YdIa?2p(PeEI*&y=ZzBdNfVtf`n<=kg%EnGuTKApnx##h2*(Y+emy zYzhq&d=bRwZTtie0t%BF7m8kQ7B>7wj%ky{E2ZWcnroR+PVsW(9SjE+Zz3p-Djlbt z1#L)%xl+({L{O^t;~fV3LYT z7)aM*twiMfX6Y*|L;M!eHc{96F2E*S$sha?rNxrG8a?XueYvyIlwhQUKmt8NUQaHi ze4N_L&`VfD?gfl_o1?h*|KCHy_~)S+kb=qJ!7ybAdLc>0cZd{?XGf539!MekwKC}$ z!NbY!O$sZChNiVV774fp0>O%2I0YLU)TLA3q8dM(HzbsHBeL0!Dv_J4>1lhm4%RFOP4Y+552A>FA_3o!?)n=fG)Mp(Ib9r_$}p_lH~v^C-zXsGI~H2_ z1bPq}PNx+*wLhDa25SzPzu`6(Kw|l9hZ3OoAJTa@A+-sB^Z`6{P)y#XBnTjD%V&{k z!vq*nhS48A096;(&ck%?y>lN*ZT`cs5z^Nt0niyN0ARZv-Zy!E!`({=fc#Ne2ja3c zzQqF5x!xO_;U5bDtcTk9`(M2$DCdAJ3Pt#GGM-dug`6!cV^o$J!)_!Soi}p z^$mWt^UGV0uTYTIp|N=sC(_FYI{aW12R&C*d6T@eGuPWDANy34;Jy0EwkS$$HP=rl zPPS?e0EUV3CaK?W;DA4XD`G3sl!)pmmHtW{l&ciw-sA}YEyD%JXxr17s9v1m@{Hh_OLVF~4B0=F&df|En`MxHAG))Kji z{lWb(@)JP5c-z{!88$q3BMhJkG3p3UpxA9UWisz>as3B4pWU|s;!B@@*6zRclcfh* zzt(Q*U+`xL-;MJk{X@1kA*J1$rtxv9BCe5;t9X+7B!F;({ z1^}WDbV+iZlUJ?0DDnC6(@?&T&P8kHCjeLe%Hsn7469V^R;m50aZV z0NO>r z_b9ox0*LH=Grzd*sU8IAlrNV9PO82Be*JppK7ZB*JUg8C+Up)3y(~Wl(59Ey8uol1 zGbemvhWydCSIM1e{{x7=Psai#)wkTpd!yd>sP=WDwlb}u2G~`x(0J*uQ1$YSn=HVK z*~`^o>*7%W0K|<`&qSRMTHgSG-!J6x*|LrbaySdV?pJ?d{Lsc>uZ@F#~e5F7Nq zxe)dTp4yd^PmkW(_s|1q^V)$%4L1%b|LfD9=Lw+W&8L#OOf3XMO=`^aQ|h)Z{f0N{ z+W?G`Ev&uif9-|4n8jj=E_8fas@p)In7y!7sK04d{CjM}f$DD0HJ5_{RGpLQd(;Si z^0{Bri%49Hz+w2Tu2a;CiqQSRih6C0 zbojuM??)@8|BXbCTji7BcoDDzXrhtCe^p2lo z0RF|J5-ggayxiWzd2>GR_=*T22zKB(*$T{Wt`_KGPlER=C7j&vv|f9lx^yASb} zwzdvt1xGNrvM(MCbJ4z}UH;nBl^Er|*Gc$#+VE`3E>3ADB`7Ho@0Y%jeBDrq#RWO# z(5FOl&p+RkwK}woEU9O{BMgh*8L7aL?{H1MEuHq#)}ZG@hz}bv3a4xwLl)l1(?8!Z ze6LqXR8>$n3tp#YGnMiUh>oX8~)tv$8lUYyO z@IRExDKG2(u((!w5`K2;CBed7+dI5_R5G&@?amwNMV5fx!J+wN%ea8!0`9cQhC>SS zN7qk$uSsMu{pwC|`^59X(4$Lhl8MX$?c+4c6H_4s&@j-jFtG73u%2LHV*JZGicW-q zN%(?+msnbp{uK|OhN&YK38R#ZmeaQ%+5Fn&qyirU+GRgDjIJKPmUE6fVUjni5Dd&2 z`=7-%6ul${DyyAkd5G^fJg#6o5>}0Dng8`B+0Kx58YL+QdY&mOtXL?5)4j*@zy18b z7mf}XmY#~pNp(7cHnOB7KJ_SPX9}LmufIO_H-!{b6yACi;D&>n5_jWgwLd>$5aFIV zygxaIHZoKsI-h*}4*+@!sksyl>jiAkINiYoHf9rQMwqOceg7j%S)oR@=|92n@jA*1 zb)lrervFa=pP>IENpxTzNqsdt%?;KDUZa8bwNUCgSTRL6gxkC>CgOG7FB+xn4H1_e z?R@J7eFlxnC=HUn%2g&&mpns(IVg^8FW8%juVGJ0biTv8W{lKgdS)AqjPfh+f;xe|C+qJ`S71JhoyZ$hD_)gD`C4jN&AH=M^$ zHJUZd^TlK9Z_KZ&b4<$OgY)7OwcW<{w;V#+=3>u6YURIWtlZKABSzmcwsk2EgRP!@ zktN5nyce{dFtIFrsd6NfOCVK1&B-KElon_ZdYU>@C4J z-mLwu&_=V*b)I$K6B5U_RJhwio`N2=zks6i+18>?5s8&HoSUo98v9xs_`6CuY-Mjs z%PNewj-k^?Ly2wG%`tmtos6kRQt8b+=B8bESdqqakNh+1+WMkl+pl<8XIejvT_JLi zLdmdGz3;>ht_9qr8lICPrBUfQvFCwHcu2*he%IiqJA;biddCq^vi&5tXph&?=hL69 zCPM^bL_0B+9L&jYqz`@%Sv;kWtdvPrg(0n;^?q9HD)M+*%vznK-xGFp1ipCG@%yDG zD>l}Dm6miRtmSPh^vqDjJ?#s&ph3#kJX|p6edjG}p1&ub=e+pWaPjE;wcaqsyJH%P zpna~FA&SB6x)^Una1(-?(7$zTQ!oHWP*4;z2QK^{T>2kQ0N8?Ls_R$lKPmKNbkCf)Z8J@0x5TH1M2 zKpOrLs{g7u?m&nhLk@_7u04z2HCCrnEtE z5>|7D`kSj1lXLgenWENun?I>RT~$|%UpxzMlN4Mo{m`H#ws^Y!i9%0LRC&*Z_!f;5 zn8)&E&Ac9RKi@Bxsn$-Af+pJr?UyMz)VO-X){+y9C+=i*K~DyJ5nFfH{Uw&*Y%ADN z!Y3{VF2{xm<4*eZsGNcph|--x_@tg~iX9I#bn!nRZllJ1gY^GB^v4_$Q$8tm1^+84 zQcWw>W#^KZq+Y6F9!@2%?g4i-9Ondu@C~YqZ@-GZl3LiyVY*1S`1@`hZ z;noc@p_5i`vk04}ug58M=^G#lW`w~km4zGnMQPh^82T?iYcA;R7s}ne(AZa4Tsi#$i?u} znJxUB%2Eu0w~VaXgMAO}H9VN7DtTm$0eRHE(J;~R5OU$Br(eIh?0k8mM%*r(7eY`Q zEb|loR)AT6H#=9VY2{1q>?rs{VaHgJHpgqKVv`uP1B9dxC+eWzY?MK?2A-*@LP0MT zCYPD?^N|rzs=1<*B{7##w5-9Ova9*LvaQ0Oy@2>UNz05geMyzEA$ziT25s%Q$=7t% zk(DVjhrN40-mn5;x3Z<27Lwm8UI|8oI@y-v21B!c&n~6ixD;`(R6prVI|Nk@;J*XI zMe_GcV20(RxEHFjtk%xS(J*{wf(>ZX`XY(&tbZZ4*?<$$gE8#Q3Iim6jM^OrW*6Wi z*no_!flu|7-#JWJ6esSfdhO>s^xP-3OzrV}D0mq|i`Q<2u==714of0L7;6@(HNwU^ zpY`cfO;-J=TKsMDzuh3ZdfePAh|-jAE!z#fvUip~2_;Ql%sxkt!#8#nei#xqwSOVk zF|2xvT!#vgXk5T?Liwgy&x`@xBh*)$?c-%gS*pzYU(a@s9cHgTpB!Y~Y0vt1J!ETE zqzt-hYes(H$?SFH1s3L zpcH%E`W!K}3Q21~+=$+NioGP6;VKtkc)iR0# zeSbH?S@~$h%Mikf4=d=lfnC9sqMr>C@*=GW(8)9S36c?&bw!e^Ll=-3KUw+BNznvK zi_{PBXimi7BtNzDVc~5cV_t_85}bdfBDx+8^M4X4!fqgI5+_#rTB|?L>^K{vD!(?_^=1o|D8sI3)tl)wMB=T?Qh_ zMbr3BASv_`e*Jx_ld^#e^65=m1#{`p(W;jzGo8q3^g`LsZqDZ2*RyIB!N2hY4XpEx z&!F$b7W-#VFbB#PQxo~PwCw$2otD`*E~q>-Zlchx_FYo_<%Y~j@zXrszL7f43J`J!dVFLDrz*LV??&VKJO0yxW{NDJc2+ zopifqwaAYFxjXMSK1&tOXHYL>fo3#l)H>%@&DJQTtJrm3>32GT^3b;T?xYPVrjWep zOq%?IX}A8t7eCcAh|l9}#(wm!o2ero%Bd=MQ~{})~QAu9vx57=L^pc7k1 z{)PI%V(B?&b4I(PR&!}p@&hk&tp)DMGqjJ4-IbfE%!Dupu_~80U zn^KdWNY+Wul`9=o@Dk5?JucbWTMj)_qpnZxw9r!_0bkTQ!mdjaJjNR;$;$^R?SERT zXs-HOt@2OqhKRuSxT)Dj4*7u%UE;-^e&|NC{=xYHN%x!T&h!+7O};gmcG_ukO+Q1f z5qZYw(Ji-l?(#W=fTg+96BJdBurim( z>Rz3+5^U!@(5ovWm_F1QpR5Y2pN-P=ndqe&FR~0T4(tXOg1p5xWX9je)5suR9UFbu zRjC@yGoS$xb__DrB`BLYXct%(R6g|+w-i*HSs;m*1JpO?^jg&qSwQ`}~Du(L;rO~{GiBr+I@ zI<3_==?Fz^{`>y#wZxuMUzFPI?C~EEsu)16IV?azb%mc*2zu7*`mn3xI=3wJbc8iQ zm`yt_f&HIoMtkI5UFGioBd7HvwH!h~BLa`ur9+e44#x^iiX~ll*zh)|YUsdj5L{(N?>E zA%OYjVhv~FtIr=s&6$;s3>8=d7$yeJ04ZhcZEiDa{z=_XJzL1%k3Y>*|4^R9FK$0- z`(so*$w#t$WonCFqt8v<*Ug9#BO%#f#v!4%f>i z^1^uqRWpOa8MQmEblsneRFvN?F1V;$&|xX1!kYw(knlD7u!+7tiRAnhn!jfbXp^x*?j44zY~OLz?p@ljHE!zv@9zcJmy=|se%MKCaII%%wA1hS8%QY?U?XiS zsdB{My4&x05RuKud`GlaxjRmUx^LK<#3}j?>E4|G2ipz^rCRX^U!By6VUjoEe<^bY zpSPV+LzGO5&E|HVxXa|en`B|c2>3#;hE0xr+)=}K^(MLN$pi6zHRT#6U6Pu$b%*P| z|A&AO&tSZ$H>(7Z<2S=@EZ?voR$YI?Y;%Hjqf0I?y3Z)UCb|!J%csG0#chM=iS&m_%My#~=4^Lf+2xkO{F6m%Q&HfBOyH zTZ)|~mvB}RQ7?`(Q%=uorIdf^^K=ag{{)A9u|;wmi+T=%K7ip2 zb^830uN_2eQ$EjjT@4cqn0Bn#{h#~;|MB-)lx%v@MkfotH&r)EuY3kmN%~FaU(;KBXT<% z0^6_MbG8xA!KS$7ep{3&!7MN!XEX8kX7P*N+{AEtiToF8N?A2U@LaTotZbpNqrN5G z4T~sI_pgD9or%tpFbh82<%P;W8;M@55F2mK+l9Gkt8YDi--ke3!{JeUqmu zh${a=D!~g9&_zMY&~%=Th4)X>4w+!%rZb9*0~?6Z`!P}j3+7Htw>t$!d{rS9D=45paha3KPdM`Bo{pzO&LGj!CfMw~+E&M~&?#h;;DiTs*9ysFMl?W~~V1sonG_*hDb1Pu%!L z3|I;--!p0@jf?=}KkO@4+$NiKY!|%W=L!rmK4=5Zd57v25ye#n{Nxeh1!~)PUq?k4 z1s3>o#23@>+E$YdO3mCGe^^n{PMo^3S{J$(|9}*KF1~lh(lle^;Y~{^CVja{v-*}S zZoH7kTRLY)*qy^M$2Pqf-tl3`wnaOHqu07tp1tD$%wkS7i`;uo(zEsiqRe)w_HM*O z)q;*xD6Yu*?11OBf6ClN#c$!LKJ6lClxn&>9~T9Sfpu9AEU{mGnOupz|7k?_=HdZTog8c(rAiy{FA%<+k z=C^JLpQGdcRHPgM+e9yv51ka`@C^;hptYrxZ*&T2=!zDSG#+m!kzU(?+$oDbe+EVS zk(Q7#c)M`*X;Q1_5;te(Q2pl`EHGSeI4kcsKlV#WjQ6b}q~O@rM?8g#e2`6Q{r90} zhOH0h_ND)Xp$6u5(cF@4o+c1XO0tMr+TW zT3fhaOf0a2_#h}!priba4e>&iynaQ2_NsV#DJz>COl?wBZ9MxKpElcA@-xVj@a0gI zV?DWG>j}(5WX}E|Tz!IMO^8FICbsxO_V=srkm}gY#u#f)u~ja1l7%5znD$pA|7^4D z5}>TQ!EisJ>Q*vof6*>Al#z)+-N~($sj;dfSI5a)`P_w>549tszKFBGv3~irw_rXF z>q(gI&x~p)RKZ=QX1rUjadEh+*ursq%o)3h0bG7fo3f+2-p?IGYq;hPiWy`#xbb(~ z|LfM2KENKm!BQ36hA4X22;aJsX^48Atmd*cyIIEYQT64|m!!aZ}t6m(R*Zbk{vswfYqHrz84V-v0fc?t7fU9b$Xsh`O1-0GfCauYE0~iq+2B` zxLr8PArzNpxAf=CSDaNbAy5@a^IoBMXSRJrT6zpi0Y0vjRg6Sglmcrr*jj@Af*Sa- zuz6^*Yf+|8tHw(x96YZyDBN(OUJ|9p%le7bcQLui7+ct0s!|xIf{fstHPeH6cD^ZF zN-zm_f1Nek2e!+~q5siYZGfBI#N~ng+WJ`L`{E?dSfQY)=4{pcK|V;kUW&4m6#l^N z{F+cM8n5+dGo0?SfTt|6PI^C!iS!I=Q%4iLsFl`c5Ijf10m1cO#hF3Su37%vLuGS` zC@{}f6mni%g6k9SvAj*+riYj!?PJXSl{kaAsQTSxF6*&l1E(Y|su)!!^+)*j+!ENC zY&!J$*0hUtG3&<{h?}4D{t!hXZSXXuD+)E*_$TtmDLY)rM2p+B@6+WM_3Q&mKfz=T z=a1a9+13<(2`FqRB#sfH<>JerNo`D5j+e}M9E*08%1?mE=zi?~Xr~fA{_=eEQ?_Om znKRwQ1F2AOlthy~g!9GszIC2YMQ3_z8pB^dRadT*U4eq?y87tMC$&Pt$5c)+Vx798 z)Nppa6?)BjNo`!+34|bOTf*Hy0GC$s`-`VQ;cTF2zt#F%ThO8fN%R{6>pR*%`Ga;r zJ^5ib!78TROZ%}jq!l4^$C36&h-7 zK`oC$W(FP=)GyzyUE$pqg(2O)RKx=|OFH&*c4!-A$xg>*3GH>)$AUP7x(iihY^FDdNb|Qepb+%5q)XxzMF54-%g>Zrtyj=V+8#j?$8+7NI-G3dirsh z^ZMz+M#RBh|I-wY=JAQp)jMW}0?0=zsd`535F)27<I*W^03Xs*Em zd%S*La6oE-++V!LLFPtMbGTz(Xv8g@$hn z*tH!szXm;sQhiz-S|~o)^1#wKQ({*j?q#xgVYt_(%k+7&yj;UaNcXHz7p3dezxv-Y zzt|l1f=v(0{s4b{)D+>PiXhas9i=# zRE(uTB0W_)RmtCOBB!>9<}HCcZ6y4Vh!FO&ORb`iA~ibOVCQ3AjQ7*~MzS{HL-7Uw z{Iit^Z*#4ebjxsTrot0_EVwfoZYM71idi{Zq&gnYxCCCbDoaH1eMG|d7nMSz^jx+Y zc%+Rd!w%%yZrIfec+QT%YT@YTnGx$>ve91!ZeIr!W>|g$6+RZaF*-HHq8a>hZO0DR zqc`q*=J_sE>ESeZg(>cS9qIfq)rk1nUd;{FbyctdPRQ2u*IE~2bfZE8Y!=)Hc1c({4N z0q8+vw3#{xwBAMy-Pi}|X<2FbtKckJhw2ns`uLJy1#9uE7Sw^Nx)s`Q3*J-fm zY&PUtdLdvZ`_La0`71~d7PfVtiL2s7)`j2enUf%HoFk0)`vc;f)zHell?W%1{#>Zc zlN-hEkJ5jr`u%KLbxAGzVEM+isZCjfv)VBNmrQismJ!x|&@R3LD(yyeiZM3xJIF5(6HdNJyT&}m zX;3*qDs@4UmjZru5DBv+{0H#-2VB)dDH_Wu!&HPjx)j#8s!o5ybVErQ>?H8)sqO?` z;LvZv=H3Km(4XM;xG?UyvaI?r*MHQCV2!82ttMk)n|p;27S0stH3tnjtFGBqY0Zs0 zOQ8BsrSlv3(4JlHY9sElr*JA?XsccDI<{eqSF=#G@kO5!RZN61bGlKt@EF`RaYIh| zC!uHrH5X{=V_@Uyy54`llV2Ta+R>=QcBWh6^Ba=Ic-{_mL87=#P&f`B(V+sKu+wSd ztk}2N2`^Z?Rk;PJNDBSUQt(KaiD<}5lcqZK=MJz!Y*eooOTXh>HMowziY`7yioO^$ z&qDQqU0Oi!kds?dgm?IGfVo^JYXRnJP~tJ~40z{&mNFLy0F?}MyAwt-ru=Sm#VrQ5 zQ>u_pSDz6XYY1ywhBvWuxq12FMC}$;s#u>Wx|3SjB@pg2w^L+e%*mC(C^6*>xiaL8 z_D?B4dW%Gdw-ctr^C1$~GF*KM@V6Z7@~kK75H(PY_)c{2`)gA^xNCOCkj;dNW(w*~ z>hk>2*5N3tra8>?4Z2z{timq-zJCpY4r*+b=qT3?NlDX$@VhWBrP<~1kpqpf1ShJ? zalv-?8j`^>ovtxgZa(AZ5H<6sqyA+d^MbBl@ze#*sCMFG5dAJAYW;=x>^ATZB?-EC zvfRS@1B9P2N!!RltP+8wx2aiirMNIqY%N~zsD@AlceyeBOkv!N&T=BCec`W2uT*%T zT$hUEH*G(iXCMAE+UmkN z^hm0oKb7r;Cj%O`CD9AT70%sws$Y4Sw(prA9IWY z3uU{getdi85A|!n?Vl5;K4vU4NJe{F0l`~9hnvNZH=q;bRU$aff5uy(0|z_~J|Me- zos&vhwaBU?1#F=?aFlqSc>Wg_Ni6U!I@%NrW+{J8Q0hJ z!^i34<=$-Ps}v`BNr)w#>-(Tr#I7>ivccW7xDVQYaDxTGFUDtF8h#h?guF;${7EiM zidUdV%#~odXXpZLZFm1L+cj0NmZrHi5%d=m9^G{aW`@{3MgQ(S^c%(>o)xTAt$@Pd z=w(*P#c$CNSc&jlF+-e0g{?B$`)%Ey*{mASir6sL5hRI+Vz>LuscF9#TSD{ zkyc=@Yy!DO_TmbN%{vCz4YrYNaV@3`X!4qCpGxSj_6Yg{^f zk5g5(=9ElKKb@el)Kt^w3j32;^0LdB9|W>i+dUZj>>2kQUSvxmPS@=;s`mRWUqjKa zs*3;-(1-F77df?G)iY}DhxMIaRWa9It;Whq`5KU3(K3Zkn4{q%p_qj0$?gGMwt}EM zy$pQo22u@qZmL2%?Kl=Dt9zDfH+%wel&KKpT^ESoGX3cIvrnjMm0{s291#)PDln3X zIC~<~v*>6{2>LmG1_@eabciv*BR2T4g}JRL@lNwk5Q%$1&FDHhb5wEEDvxm5qnOY!GpRnNU(x9rmACcHCfXmvK3vC*3A zSkj|lwNS=0Jpr&;HO|6>b}6~Qp{nZ3Z+L|rN5-~wFnlX?uI@e@V_^b$nQz^^6%MuF zON9%uC8QaTP_tl95(XZr@xm%LUr9XU>fmd({ zVJmwELWKi7BgH)-moGYNkANsuTd=y_k(>YDzolfozLV90Z zKk~MiIH!{;-u>0+Va`<0rodqCdw9)GON=HMH0ER<^P!i|`)>}*Udzc)W#jeJVqtZc z^8{MMDYcz_v`{bSkVAi?lz1XtO9+JrbGQO_Rrv{%)oECtrjz5AM{vGk1;=fln%I`o z=$o;VDJ1Xta;l2xHWZZW;qLrnrcp@ne3<5sru(Hm0nVF7cV-^kbbo+Gx$l1^XIV{N7s;%kdb}==GXXDil@R!A8n&}zvi`!1PzXf zXl>BfK5aL0v0`oq)|bbM{5gzF8lUJEYT=&XVB^%(;4bRXL5z$22)hA1#D0dXjd-&T z$$)YQtork?*fI9}xoX%ZL{d-VE3c`0>!sd_-ZS;-*S4dy^L~1{HrZVd})sQO48tRG7A_Vo0qPOq(R><)mia%%&q@wEnV*c$A4}YtC!J zx2La8JYH-kXqV_bH?n%I5(9st;ycwhpMeKc$mQqp5q@=W|IL$~RV5IfJ4pQ(xj?GI zO}qUFhejJs1Kv!vN(pQQ${QcG?7nA9swoSqyAk0f#}X}MF!WCAP1{F!4&CS%uE*<8 z?ZnP8=q(C9_kx?!^w(rcn!NnFy1xD?6JFRWID52up_}7%+b`!z9i)27Q|H<)=kVP3=Q*H8DnV|yi*Ue zT|(6y%SHVy(MI1zUedL*9=pmter>B*n1$=yReeE}C9UkL&d2;{r37NkDI(KcYi29>eE`3CWb4}I5W}#3p1+yNV7Vc(kvsSKB4A`>Q zt0NlFQz=6+5<^dvmCG#`OR$V~RO6vOGNzzV zoAOu`!lJH-x-`r%YGZCKhA3VV@a=j$C%W8z`7VHLs-WcvK99<(;j5Fbb3c}8jF1jK zjI9;z7S@xbNZ&2x%d_awjkzhHRxk^lwTAb$zbQ)jBzMg%QhJkVz9op7gXC&%>139g zN+HRrK1A&ne-;Q25?KXzCem`H*<7_ZrS-?=3_La?!WWKYw>TYJ>BMucgTG+cj`3iZO|9|aFw8)O zY&-0$S1JYOyGV75p5*sdo={P)_K6L_J9%;E@bEW)~FfK&Y#{OXtO<04VBL3%?jw>3f zU!)jhDe((`+X@KFdp=GOQ)v3pL3)%rdLvQE z37<%BBeMjJwMLj;$=Q=$se?q?bv~43>)*rGZq=t&IVVWQ)Re0B(}HNAJwgd!+5S;F zgU(;<1ct@JoZBXu1cuQ#iumV4e|G_;-D|{GBoX;Hb~!6a0>@tyuei~nzla8?^R54k z$9k)a{n#gDa`l0>ZiantOUMzR3w=AVOY~($X>9A6-IeAv*SCJC`0M<*zu)o|&TzL} zm`A_uy-mY!|y!jQ^FERoNbnpDx*L^!zm%mNCW+bdg;&wpJa#kd&I*a8fv zPI&yEh6vFY30A%}T)2u%Q1Z|hjV4|T+m0ICetxBaYh*$)FFJ%#-;YS2VH>xs2wQN) z36oM9<;~%>SHu=6vZVTLy6T97tMX#AHarOU#9NQ0he+<&+-mxisgAGc*x{pzFIsEJ z6^v7GSXWiGnLPN)3Dc&=|MSA&O__|@F`a_Chw58jCh^ttKpj0H2HtD5){$xId+{aNWc~+i{wePV!Ay#Ag zYz_40@VVMWMbxt#lcn+-c@&CXwQCMhRH=kRK(%kGqoR57^4?p~oO<`OxLr=S3Z=Nxj@~2FxN4QR-uJ)86MVLjz{t2O@L%8B=l_k6bLU!g7v1$>KlQj8bIl61mFr7JKTr^v4_!w(P)Sv?;W9FyB= z1Las(KkgvKOr1l02lrlCa?zGev#Plh$kHl&2XFaG8p|3vr=LG~VR$w<5fn_I1#PLn zeknKnnndNCF-}nSuHh+*h$npqvnM_LC#!Woxl+9LmEoX4w4vs7_miQE$|EppJ~kW< zA5|T6Y4qLFyGZj?WG6E$)^p-t&v@5lc;HRZl%03Wb^-tJ!ZM&^*wxgsp{#OISMRWx z^9o9KtZUG2YLE47CA*14C?Mom<1H&S2>~897Dj-7g&s$v;o-UnUz153+oHC!vmNdE z2@w;vDH6M?mPv6=e5W;d-TtP8&Rn~cGm@D=X*?C*V+pxu0?C6N>!x>qbSDiT_*ch2!Y~*}Dem{bQ~nWc zR6*3(+l2=avs^zqU3>{;7rhdv;Rp$KNj(&0b7XJx=f)9BfqLOs!2{=9KicGaJ9R=I z=WUC#?ABCg%z`8LN@3=YQBLXubz}v$&aU{Lv_u2Kcyv#gPz#epzh1E+k54tw_zPn`mzi4~QsJ4UdU6ev8 z?pCz8OH0upE$*HKr?|U2E$;5_65QP#iaW)fKyfJElfLgc|9jTD_v=k2zsbtV?D0J_ zd-i_z|Lf0U!+B$8D37E=<-jGA4=%wn@BIxDe{-dxtdzE#3IEHCcMc9()650ezY&UU zy!Wo{#or2W$)LkS6O~66?YOt9Rqzyi&$}b>4Ip! z5-(w*`Wq>oPSxzHdpm=`!^nD(wdI^PhveH1PZ2~ZOp*OC63X4abHsE&cH+@y$fA?V zDDtR=ZJ>`~a!KEvnvYD+N>IJ8P&S3z+ef>S_rJ(%obCGOU;y1p;Y5=?cIeXYq! zFE&NPs-CHYS||?eKg}q1L>)c1k_PRQb6^qGu3Ya3%vkaHfrf=v_D7KSU_Q!9%DYI9 zX1F8j;oi`etk}!`|G&gfZ$ z?jeTrmXfXu20#Pk{*@*db1_?Q8l2p2`)aYE^`lpe!>9=pmaHBlzyiy*?1@Ecci}!p zo?A-qYqnTb#sw~CYpdCq;L)wDXZvD|L4MY|?{iTr6^*Puaa$rV6Ou-DH z#qxjqhxHy2ue}JsyWLep1a?7=->5`mmv`$+KKF0!f=2JBK#qObl!8vn zRTH;9F|JzSVhVAM0_HS(8oFuLp$I|%nv-G4XX;0AXQe5EME#&vq&O&c;q<2Q#$*TI^fJ@xt8UgDJ~VS&&~du76)DG zS?h$-dM-l5Gu_CiYBTpYq`Pr2PU=Nk9vwPohmdcibu>~^!{aDa1)FrxJV`6mDbY|1 z^R?|x_sZ#9fhu7GYZQve5z&kS6njheB54bTPF%&V)_<(6ke{K5Z3@@76Gj{3`Rgn^ zpb2S3Qp=}%MnIQlaTs<l|$czfxMfp{UpQ zNi-?>^@7(pS3x1!i6|@pw({l&1IZ zZt-R!4m>{>_>x|}hE1kwgp6+^pFj&1ee!(I6xftP426Q?1YV3`**yEr@Xw*)x$j>D z`g|qL6W7t^KS!w|W={GTrpOnWqxWz6_J*BnE8)+={e}5Lp@dxxAm8FuOSAh)I@|RL zS?hTq%zsTlzC2=r&CvpBP+TPMV}bPVCdxyW33{#73HGfr*I$gr5&_aufrDtj!jGNIR#N&iFCel5v%vV z1e_vA&p{S|g3@_o12`75-S+(%<&6lEyKSa{hUAM;wR}sbto({au6|EKb8HcHD{Xbk ztW$U2u74%<0c$dDV-=qc?14y}%U3@(;3(2#7nwp<+j&}x0z69;1FWAc^M>S&E4j)V z6CtXpzPod3R^*GA5A?HzWaxr!NlF=1zy4e*ekAaH@!ODQBTysTR3*8YhfT_nYEv6h z0o~stNid)g20u{<7rUVIxdOoFZKBm~l8G&X_CF!+Sn6c8 zqe2XIG4e_&dY!+f=KSL$B6vzQb?9Et zCW}D@YOH9vEK+rJRO%(G7TJ=0D@Xsi7s!|GN#X+&w?T8>{#L4ht)3ARkc=F8RFPE_ zd*Je-b|wj>foN8Gz2%lwKsvo_p#_qszMPR`ljP7(&H2bSOMyA?9GrV*Ko817EfB+Y zOSZCH3a%c_lJ6xUnp&w0!_)E~!yZ;5mp79%E#LJ?z)LqHgRr_Vqxa3~s`ME-fm+Dh z>(=mu$b$=-JBF*cCMIE(=G`W0D@raa{IkHuhQJ6;_pdY)YJ)+ew=bTzZC^{dg^0lB zHPqRs@bF#a*a99pLw=!S>ut{ntEwDqNNfFTw3HQQ5+!alxvyi`4RhE1>dT>`MadCX zgdlbf64Bx(fr=;Qsy>meN^U0pL_|1)UTa&(6yqIes%|V<14Y zCLJ96nG5(%hUbSmxrKBuHpUv66enhw?lN8VCrS!ow;hTLprQba37i`+B)?M6BKZs) z-Y`MJm1@epcXsO#KPn(LvrWsptwG+a?}iw(Mu^vIaHj0eN++@fQyWJ0|IZ^&G)9@6 zz4Agk|M$oZ#-QK=43%$saCrtOJd%UH2yy#}bUxAQPtb z`?E7ha$c7rk0mM=XHpDO2qzjc7#A9-eP?J0$wc-VO8;`lt;t41QU0fR3^She&p!a# z5)P?CT!any4XOG+Av_kh?8F|WDX1X=XXg5AEG)hMm6ruA`M>F4#Wr9;(U9%?4*?*f zipR0IWy6#sz+~ohNcAsVUC*Z9X$|k@6D!7_*KstT^ST}(*spy;``^9B;r=A!oU_tw zXh?O`#CRA`T>TjQx>L|8KUz8ar`QG)ob$9m5&TVDtcxICgEF*+}8Etx<)?odgkB2_RV~@~&pw~F^ z|Kv)55dLFO%JZQ*JxG4r9uSRkhFK^*1J_v#@b?q%kFY%dP-iLpF-N>zS`phvNkWL` z9o=`Yzi=k?b{#cXuxkB>I4q8V5x?pa+SB+)e}v0H1t%R=!9WLbO-gdvL)Psku~V#ot6+ z@t-G-yMuH1bOrJO(!gbMMZS_|gwQkj;?vBmMYkC7p&nfSawR+m-imbs)5ZxKEhF7c z-`Jafd!nnkPD%TkEW#`y;TFZUXzKGB<*e$bMFQ8H0o&hd@|T)tqrj4ejm%keavwc> zN9sr4rG9T&e+KsbcXS3c0*AsP`^|D$3ql_)7}XrMvf_krV2gHlq?86z>Zgt~secBo zueJM13MiF{8|E!*F1!l8g$M8}-Rs)C49zIf(QZ_QR3m45Fea!+4tEWnmcMvWcJB}3 z@12N*!CWR?cME^DFYaZ`RHQwZl3<2io$CGa9}^_dk>^L}t3S)$vk*M8)Y8@W_iBA`Kn>a9b4!A-tq2PR&2oX!DAO71QF97TVVTQ!Ub#3f*zyB~Shw zwIwPDe&-&igl*?)wghWB2TWKVV;W9Z_Y`f1~plHkBCvoOY6NfZ!Vw~Rh8y??h zCz$YvU*e1Qu^Kn|dZ$641gy$rCTlG}y5s+|8(KO3bU%J$o(OgRAaTotgf8f5DW4#S zSDIp)-Z!AAizgb;I%p(3o%5ENQf-w?;1B)6Tc<{C@W?@{nq4MB2;BV`WZA23%pMPk19Mw zTPW4d+onM(`-s^BpflaMMde)-8hBf+rR!N6yorml7;UzU`?HN)V>H;&p+{4J-&Bix z7d@?w^oRCs-Zbixk2yWi-|S>y8%fm_B8C}CjFSx2QmS}5Odg;szTqUHYQ_gSWGK0n zV#4-eL3fIkem_)SX1inLm)gIU@#3)nilpF?xExq4l)WU3XbBTtgpi$CJ=yX4wlk)>$CJUkv?htUHreaI7XZ~9oXU_ek?7PoufOx2`yyG^*d^6FveKyd z;*(~meayi>4TR~Ieoj*|Ct*UP3uLq$wZBjqG|qkr%O9$(`MOpag;6D@)k2d`B+)B* zo8IqisO;`YgF)}`VF8KDQrYK&k0-}Z)T*ChRzvEl4Z_i4JQqMVZLy#|Od@SvZu_T# zr7}y{2?m=YZ6-rIvBJxX%}l5=IWzxx2Y`;rsJ4@TtXd@Nr*V_V39YPQaS>B9SoTo0H!Wmf=WR~Byyk#iqq;u1LDHGySL);#wRE9jc)xu5#<*51Tako3c<27iKURUpawL{rqTtCwOW277IRN~ z14E5ICnE&_mRk>X`_oc3*Vd|LevA*u2j(Hxtit6V7^NkZett^LC|MTczJ;iA#(MpV$4z^%a?_$WO-AT5 z)9tnGL|!)}&nDW&CI;lO|$R5n7}+zD6+tw;vuO7}#ACbnWouSC`e*{Kw^ z_gKA2=9!~T<1@E*X}yDg{j0Xuf2-Zv_1_j??c7i4sN4C! z-kPpFPydeHUWq|ehN^X{C7rV4xiAc1h3PugA|+}M`1@nCcv&RSpo~-k@>@^JV2E(( z4fPiGW2I5sZxcm7?nz;^uf;A3?deT6Bm9)vYuGC?=a$F84VLMr1fq4RjIyuQiJ@BCIljkhGJ+WA#yIu?B}?}q z1B9Oj<=kLqDuoWJd}SKJ@wIRARPmcV2Y3l0I&n8xur>OI2xkn*z&vG!0}Ejg(ZP)( z!<|B=F45tBI?mSeUhhTis_E*vr0VjCIcV#8`cy;E%-H1~>8Y=LnMFuxH!no7s$TXt6XR49QEZ10G zm9Lg;noV;hr_#30p8_^zQ!l@hbz*#|ry%=X=4!|p6x0K+WuWiZ;v336ESY3lqOc%m zmBJ-5ZN|twIa62}7Z!kqR&y<>J!g@SjayGF?vpHmK#c!eVREfm_Js(l)=UrmzM;bD z$+kqmNbMJ7xzF-`jgY3-vi?t^TM`Vt#wFz5Kl&n%wA=KTq3aj>nlFU#a}mKeTH2*S zKUTLtZI!ODEKMfylYzX1v;}R_@bZ&l_=8kdczAErS|~%$Rb~R^sd^QgkFc3GAr$Rb zr(_Z`os}H+R^kb<-|B6;`i2KSqI(NU$4?a7G>u@A~jbR((Ikc zi8z>lX8%dA~RW599VSAW({Ix>u}(`V27O-;0I2w0lh z&7I6uvHv&-5`3Z6+IYi9x&!iJvn0Uafimz&O^SCHjr+AzCSa+Sp(Gv>?s{qnlQDfnZJCW^Ti+$>enf^}u%Iq4xYd9J zxXomGvWzPh(_?H!q}vq({L$RI!ym2~;!>z1(pTp*UrXKTw2r6onOEQR9VK^GJ<>nO z&IFUZDI@OsEH;*0Ti)NH#i?+WRj;~r*%M?^edt<2pc|Y`Ve={WiG#)3Vx~Z(ZD){t zsVgdas;&h5gVo8YG8>YG%3ZPeL#7^_QRmh%Z+&NAUAN+@f9=EI5u}^fc*5O=)Pe=M z@?mz#(EwTx@}nd(-;&Cl!iA)w86Ifbz|9!+t76Ffq|t9ccSPcD3CqmWO4pVgJ<=LA zEm*y5!8qxCKL*wTo(U0i7IVzt@kYx#&s!&l{~nahj3Id9fkFA(cbonCLir;4l4bpz z)AHW|jr;&u{ZjK3aij@Z{bU`Y4pJS~%UF@G&wQ<5z60F3h5(7(SZscrmxWKsRS4lP14fTy( z%B9*sT=MKaQY)_h=gWu16+g&75vz;dCL_?n04|0A9A#-!4s!}H&tdc_F1+9!X2QgHKk#CRJuG(qctJAu6fB8 zS!2t*Vg68*j?i%6S6!N|%nU43jVQjhXIj#nN`IicmC~H`HKTnAitm*Tvitp67yx+% zSFN6vNTvq2V|jp|6g+{)!2I54uiaL)##vudU9f?d<#mA{FP-|dhis6@OAD*ps0TQE za{2!5yUTnzF!$6sD-f~>x!tu=HIg`N%BuQhG1VWeZ{BpPK(8|V(;`-2?)M@ja;2@B zx7TC8fPmNLvwrX%m!5<6o06Dx-O&9`kKZL$O{-29+o>eauQ%bhJ4t7xSb+*CASX)pg0rnSUBUN!?a`KN!DP` zDXzA`1=3fkgf_1AETU?)Yx6ytaIvrl2?YLi9f4+` z=>SN$o^(;fw8_pbbucdQXkESWI!_WJ50BoMQ%svv+agM=B(>ZLW-L+SNbfhsu&A3) zkNUa8M}D=Ivj+vYR2>)UtiQDy)Ux179vctj$qV#eiqKECw_6ga(nr5 z#7+;~M^42ct4#Z9mKLO%lofTb2$O6y%l@im(yX|@nXA15PD9MF<2n7^=ryfc)c(TF zLkzt>N%|e6kE^AbxMk1ZO!jxvj&ZLy4ez5y^{Sf&G2j2DdQ~nZmHa&AYZ<(l)R~xN z;Uk&uUJqVWGs)XYxWrI$*mg@u*OgpbglfP&<@YRk0D{!TzJEq))z*>-uc+ajJyR?` z7bJlBalzNGFh~|45X)^)TC0rcIGL0rPs9^gNZl`9xFuTjlnr+0yYLz5c6+X%c+2#+zF&ueIW|uJ!o3H(zvS5_oI>pKZ3t0;klmHq zt+=hUtapmp9xtE zR^;=86BZ8Ng9v+1QaA99w|^4DFsvq7IHMT{`5_f6pfW`>w9vLF26f1){5)hs3I7;a zuGmucy+4qdLMd65ngF77l90=>*OL^3DWz##oPl-vlKwdnZZqCqqDA zM+bq$tI7fr`ha6nc12suAqQnhPsI&%wgA+KL||AR794j6lI_uc=YgIC zp7mbRcsq*95w;zsQ@t(uXU5i1TEo?67@4l9E z!)csIh_GQ|nD6XBR;^ThQC&H=6C4ctgk={IOEtB@$rB5o-T)e4I7?1C!~B6xKZ1;{ z{7k@~GE!k9nSm~a8Gtc7C?2?-HDO)C1NazIhV>T?8>SUhPL4`p1G@bVABlOZbRn4X z7f$7)TEFG+mrksTP^G1@md-`r@T9CJJEj>U6dF@S%bEMzS6<&{mnK^rwn`Bz~eK)7({=I@bO>}lF3D8=yS`lT!qrxtn3FNHg z`NdKOQ~Zp8Vmoh@Yga^@ITr<{)ieb$;@@Si-`(>%-YCoeR0o2H}SUbO2@?$|`vwqcsXQmY9o(NC&$_HTG zpkAcAA5H91Qx5K%kj*1Z@z*eDxl|gdrfK+WXIYk@^>M83(R0B&Pc1_po$D}!z@qYy z01Dc1yl6{l+^Q8wfA1J=S>foLUQPe{Bz5@6BE!}Mwx0)mfp}o7{u+AXiy=@lCtJ^E zm68T^Z?kq;%P*Eqde*@&KJ4cWo5?%9Ek~FTvx2;q{R~n^)0U-F>yOpea`lAc?rHZY z9CKlM)X7GN+!cgX<-3U}HG0z5qYO|M*!+dt0a=pl0jTlFwNkdvH7dEajN5SDWmCEU zkHgax_f@K3Xi%C@5U=orUSfV({`W`J4(vru&m4u_a zU-=ZrSzwg_VTC=6xm#Y!)F_&*uq!ifQYKBmy5Fj3QrD`qYlu5?4eIaa-iJXqTBwx7 z{Y>2gL*8AL&HmpVS7NMRGF>Q`CEH?G$PxBftX!^|0d4FUfd+CO^wmGe9U<1jy#95S7#@SF8Ft7WljA+x-va79{l{ zPCYLZA30M&kt8umvG4K?Y7HKW5oPkICaup4Evkeer^S%3Hj0K>d+tso4uV&Db`B^PB^%A)sa zIPw(|D2|($*Q-JL4i}O5XTXI}5Hl~IRcKP+Pih)EVp+H>_=SJscLORo-TamI_Sdc4 zpE@KujzqoWgmUSTx(WvwD=KXbV=vX_&u!l%p0v96RUQfcMXHY+s|$bO*i&YF7potD zUEy=K<(B$Jt37YB%{!w>|3s<9AaLd^vY0-0$>pxvB*3KIAOouv)z0|R{>G9{ZH*^| zY6Ee_iSPiMz5ooOYlqu+1%qHL*pay&XvJ)Oo%GG>iSJ=)$A-Utg`dWW0%~U?`QCm; zt0PZxP9i(>cSs{liniA}B-56q!$+#BD=mOy+}G?O4%W{zdv7u1x9`p;pQjRsm(IhbDYZ zVq@H5BokTGB)oy+x?oTlD6iv1n`}XEL3LU?9M1MTYa(tcFF{>F*xF1Ss7W%hfmt%O zxIa`{+fpk%Dw?oZM3GRT=tunQPJHYRcCz&hn-?}J=?@0?P&X}3Xyv??8JVe zE6dU6F~571V@KeTxVp4M9DSZ{I>;UMJ{L33MK0alGSi(n@p%nAdh4Ac((sFc_(is+_Gg*iD9~VaZlf~FCx59X zp85+;tXQ9sA&|=^Y9} zcX>bi`6ssveq|1!?#O!D|B!Q33HE%lymd8uM{Pnhfuto=qK5HMU{rdjLbe#5rKv=K zkz8Pd9!aiq8}wu0!yYthqVk;*dQ#bPdF#aUFoRinGz{$)nt8<5-@+>ODeS?IB;L}j z=R9$v-WyD0G3;o!Q&9b}cjwFU*YSr#@$d#rblt=4a2IclvUL_gm)*1y06{g zYdHro&zF-*rAXnewu|*p%PeqDS`5sJ?BG=E_K|DuxwTZ5*94O-^U4HT3J$cSPBUm( z3W`1SceFn*Zsgh$^3`^b$i@YAh-j~)GBxB}`w`hU_-DaTTiwk& znayzlN!%D+M@L?9KWe#F(Na-&oV5O2WAif$UL*w?Uj0-hWXKRe_0_Q&=|1nNGSaq-2M-K z#G1+nrAM|PyD`5RYZhO%*RY>Xo)a{~No3Wg)jd9jLV7-;9?C$D_y@;r(I4K_FpwZ)z2HHMfIJA$Z^vY1JN4uh!{J*;iLnlc6c|+8(&NU9iCXYqwXpsst~XU zp6HtoKKYJTK2(0Iv+^|}I)!Ye4{H4=P&Yo585MKS$q&AKVzk4}>rk5cx|1tD7JT_d z0wL^?m2Jm20?j?~>lnV{OE|2=vnL;Z{Dpe~F^l~6iYP$0%~Gx(|75hLn2A?$ub~_B z@lEJXcdgmb`BCXgS!<#L){f9s$6^eYfpUHAyfIY%IlYO{ny#H&Gp~`1gmeFiz!%|V zIEYAz8hEvHbW9~B_V(su5UyMCG{dTBtTmBoHsx6d)2YP~{oQTG?&yc)ZbiqBQIxd&^OVHeNA|HeQB76ZZI@Fe|g@951t=CLWz5>a8jR z7zK<9BU466!&2zO!TTn@XkJXh{vL)&A_JhO2m1u%!IA=`;}w2sGQg+=2`Zzk6(=&P z$y)pu{JA6=`I++DWlyVRf}NpQHY>&|HL`S|s&V0QEWXZrkkgi5KBy22$L_^DVJF_( zQ3g;Kn1lA#gc+|Q6&@H4N}ZKqkYP9mM$z=^;?2Cp7UA@y%Qp@?86RvQjDJRF_zTmX zf|pCN+^4FCNvCcJe(a5t+9ivPn1|+GkMhh5V@W;wjFS*fJgCDU#c2}?VPzeqi37;c z9>vSdI_H#Vf&1c16RuhL2g&N*-6~5~;NrVk#odc%pyls51THkL%}~_?LaA*pg}AM7 zxNvlyVtN>bq#=Viu`z2^zmfU%#He@9RpAAoch% zLcaT6{Zg!oxl@@v`wwMV1%r=Q;8C$uDt5g2if#rxF{!EpEwt4RmZrg z*S*9Q%dmIW-;{6r+5vAv^cLPrJy8Fw3bg=mGu)fqn}4n3rgi%~9T~@Mi2)3r{KOPB z?WL~|Ol&d{+Cj#_jm}LxParJ@%6;RUE#9kqOPeD85@5mPilNBJ8$8kH;14DN6J)~$+gKvvKf%P8B#f(7=Hj|Qn;gZQwqdY{yB+x4}`y{w#HUeDQc^ z=;}?o6o2prtYzPCS)7FlnJVbpuyo=nPRdgF-%&gODY-BGRh#@usF7uEIne0Esy!mWBdrhnLM#6wNp z$C-@1C_Ply{voyUz82jOl{Eh$uTD`D=35qyrBDy{%el{O1}50hLI!S%^o%DIcU}44;);F{V9JUO3eLL{ z$d0+03mKrhDbq{W>#Ox~*Cz1n&hVkqo4LaW2bm|;SVh#2!i+Rl&uT`FS`?JEh4e=1 z?@jxgLR7f>#S-Q*3X9q-iLIBzMs#S5C@mMh)S`Phi_RZ}b3O+SLb0Grg82TYAraC^ zF|qx);z-%aVGHXW)T|{f0G#9(U7CW_!SmDyP6IG)nbs^tt@XiVxsV26(mCkJ6sNZMw9a6G z(+>ZQ7g3#Jg0)~I+s~>1CJIp@Rg*gu=cspiq*78(=BsPJkfTEJA>50c`wlK@Oc&Ch z|6^|U^!X*^nFU9Hs4afl1m_J>+!>$?m+qS(?v)0cvQ(Sj^jyKLAzQmqKQfOQ3mT+9qXB(mHA!tPIc@f>$_yb5ou%U3$pm4ybfjB4&T}2 zmAjTdeSANY-P-S0gCI4C=M_{0d1z zF!vq2MP6fl=s+LT4x2CP%vRG0Zda`;qIFSG)c<`C5m)Wh&^R}>QQ_@}K%qjW_~ zK7;Q~4o-)43d>4UTD!F9=*~WBU+^}oPHPGL7#h^9cp_YROx8ozn73(#1Y&Pp`yIX> z6SMEEoGE5~T(W69vMNq(NHX|ZYdB@5l9!%?^jX>tcMohq13t1CGd40BkE>z}&<;JL zRf;#7dY3aTW_lol8VHrONeWIjksM^>ArDV1DS5LfI{slT+jz7-o{<@c(TGjB@Mk6W zCx13`eiB2|fMuCFR+qF1E?J4P+|o1th{ox>rqDJg9<$LKWKPpRRiY%-e0U|^+F$R$ zyv`=*(?<^`Ie6jtcfkW}4r*=bF}Q|_tmRu_?hWF~4=j(~NiPI90cL~}E@45*rGy6w zNKB6LHo++l1B`(g=7^i-6WG6On%%aY)2P$)xVAN^QMZ{J`4i$@lT1(wQGe(=EU)N< zn^{5QoQ?vb{dIs3a(Hsl53E)K=3WjFKi75l(ozv#dP|J67e*qTS#43>tkcXP_KALH za~CCfC<*lPjw6-57Mm8j`cu|~_5JyHx@(Ycr!{ZQDQBhG*904#xIBaq$6}Y9paQwLG)ZyrN zAEtT8Q|F5ymM=5(rw*BB6v@uV)J5WHpC}x)NCOXP!%&f=#87_ zCE?)(VrPn+ist^pO`@DK#vR~?s!&Hq+8Y%w)_A-{SM6N_>?C2H$~woYe50JDb83o1 z87UR5d&1{41XZ!itnudM8>fYc`iNTKzbo%U8UI+0vcGJ5k_S_0pTrnTGN2zugj(i& zwSa8JXL9)-tF{wR9h*rnk^MA|=m>B;lnDsBWBF*<^ik$1VtHnmpDmG=^L-V@cn(^= zq$5yfPD3>5&yox53W+hD`upJ0<(vA8VlY`l9TnancS7nB#$*EXCQYv4$yPQbG|)Pz zT6!mbR=?OBK&9fIKt0mD<@@F}f*kz*sWIoZmwuEb?s)MpTtMLP>8HFquUB3A=_Ki! z6TiN&kYyvW(?8GELthrNLKV2=(0x{?uHznPGiZ~-x(I1bfX5@pdWMYeY;2@%De$Een)6nfC$wMEO&??akyL|uC z&F&{s>T3nB6_~rhZ?)0mX?M?3L|h}Rv#Ej6l_#tP(~ZnEU$5OHapgR}A(~hS*C{!G zJ0=!>RSDqWRd#Sz$Jear)@CBd1thM=4=BrUq?KcI-BK`C+G|@S$|IX=bByGtNjy~_ z&F7LbvRG5S3bC@XP?tOQv0FgP?DSAuC;;UuMq&!wkRpNo_0pF}2ib3@i~#K`M}`81 zbPD6&YlNVr6_WV)q91BBFZ^DXfZ#;MpR2y@mlg&FEZm@0146D_U~@I14i;&gC9Ao` z0*JN5y}j`T{U0Hw{~=`fix)A;#8tGguuLB~@)u6gcQrb%NUfeHr|KE}XqC6>Qefn44Xmx|ims6@8+k?L@HMQHMw9XxnHbPR}b)-Ciip-Krb- z(VYTN&~B*`4~iZN5;iPe4Xc%PXiZq9F%y|GjyesxZxRHm$j_!Gpm@GpAE?ZGvq4{Z zl9vV{;bte#P`1}J{JJ?FFA2>WY?=KON{;^!o?%HJ^^XEX-1>;WBCa#Gn;<4l6oIJ- z&yFo8Gv4{?x}13+xSL7`bQbz&%!pgD_}l)bYPGXeml|=Y$>#@C?tNPx+q3iQb7|Qi zWLb(#E42sAJFk$DdfUHnpF6X+uULO|ztpLTSZ{+FKhrj>z<5s$NKD!ND0d}L1Ey_0 zGRN#>{qXgdv&M(Cu*ez_ojpU7=$yyBjG7r|hH-LeaC*VFm_VYGrhRtioLDi;f(B*k z2Q|XY6eXJ$u^SMJ*cfYUy>Vfbu0CG1*d>p!Q8w!E>if8m%r=j~9i7pwM{kJY=&s0}c51VX!aD1!z^@0=dEihA1N zD~{)_SKAWzC3PQUu$A+uB5i5c>(GlOBM0xdb0g@UoJnF$t!PK)>RT1a|Bz)3)pj%f z5HV1F?(wI^22@`K5+LWXa~nUNxOJC2&{c&;KYV{pw0WlXPR!%PYapl^q@VD%i!Y&aa7|fWtEI^6ak63s@`6sRG3bA*Bxl4)msg zN!bgP9Cv$YBUOa@$^8`yc*@Z8oz)TD(obn+CNFsVGDpR2vj?VLM#Q}*Vkg3dsA6`whUxhKZ-(;N5N zzlOYir-|dSt$q6{AybYjBrs>(M*qGqBPVnI%TSSivV<(gmIghw6qmF+CpxMlIGHC4 z{9%tk>q~(%ZA34ZI2`o)2mQ=1M0#oQwI>`$MIs&Zzi@;%f6Pe&rNx{dWpGR0(jNhj z@e3DspYe>RuX5tWbCNBJN+i&w^Bf!IGt0X_?O2#dEl00gR_(cv8T;!mHu?Hn!2_l% zbzYdi46#eOu5?&uqOiB@ag>%Jcp;KfuF09QO6{3)eGH6aI3a9i@5r~=i!HfZlP%K< zsDCyjfw|0vmsgF|RYe1%FzZ+#3N6yo&!;UrVwpU!8;}bS4%|^@9=G8-)x#sc^Pa_0 zS@+haOPWlZhquL@{d_eh_i)?rW&>fG8RL zPWU3P4IWbEAH~+jJPz}UBzGCs2ppvyZ;Rg|Y>670;arnpWMt%y^6-@rB1XZsmN8md z>P4N|z>Pzkw&yB%&&K<#pV*+=HM#%)AJNk1mw34LO}?Ppu+m+KNz?b|3qc zf6oTHW!3+DXnHjA(}Cdk)=*McoDx?$CQKRZ{PG7!?gs*{E8rWgh#Q}`LLY)?&`=Q} zol2^Jf$r`|pi({ojsfXWW1|EoJ`(5n%I^;e8JKQiRI9a6-CDCQ^@KKfMqCiT7Ygyyy?$HgC;;)?4nwNfd%O= ziihI9oWHaY@o7V)a{(J8C#Rt{bxiPdbK;DeuC-kG6q6Mp8aB&z65X-amV#Q|8lfcK;hH|uQ_2JP(l&-*Re-0Gi+N%K%Y zdFNG!l&=17Va}vYXe41!AU!UK;7I73N?3CoO%`~0c9$KwBFG-}hiHdds)&F#FEyRz zL*AvY8T_Z;TQG0#2x(V zb!S97<+1jE#=ukZe>yM|8Z29qb&Y&X)ZqV+?T4P=Du$x5d=ypu`W`p7RNY90$?Prl z?sB=54WA@VGHqgDL0YTut!q{E0ln?;E!Qf@Ows1+x z`HPCSPEV<7<=Vcg$#}~|v=AQUH_vau>ToBD87QFqG7R*!pJ^xpG{#y7(v%$|E38Zp z6sAJS_!(+Hq($E~ikW*RQPz^=)9;A5cbxH5D5FLQr92A=OIS)4h_ms$4@&)A8E5jY zua=8mAx_GqbN?Q!7q>*OH^}6LdernDDv^`h*S816{v^2C)Y`J9f*O$EPuAaknpXE) ztWMdaUf@cvJE$?=MS-tJ#^zQg4`;#O0qf!|KN?bXajHRzI<+$9>C?lX;pqr># zwyz;c9L&Q@^r^I*R0RUc){CNL$e~g{YeO@BZeY1Cnz~^@A%02TXBm{_m5-@MP_1l^ zeu;;8-s?o#97B%0qV{2%cvov>F)>lX_mz1i@lR^hQ}0!#JtOEOB_i;Zjkyn4(RX`xv{a~G9fqd! zmP!jHT_=gju=rQ4Yr~hDj?`a}XAUW9%lz4ZkhpU-<#SUf@*Y`@Mf6z__imJnPnnfO zxRwmUo5z~6BK)xe7~I8Sn+EU_K}GMl3K>$mVuy-cx>OKVKI`d211IMAI;DOHb-~tk<)@TCpg~)b zxC6QkTGm}{min5xkrg?^+ny4<1$or71L1$j6*Ttwbw`WN~uZ) z?E`Kprt2@_ zUGY)Y@)?+XP)Y#>)8EM|J(%w4KSxtFkWRPNTaFn;66fRoawiqFPQr2Os2hD72%rGf zy&My?qwnWZi_Dj8BOwAxpkTI?(;t77sA1AAWvH<%OiwFFla4p~5QI|KtAi=BN}TEb89vaW-&?%VzZ7o8H#1Xu@<`QmK*OYE`L z(Z|MP4k0_PdbgJ7`^yj!V~1a#@dcm#OyE>##jeAh+R|HP)PVfYWV!>UCQ{1I3?rsfIibJ9BT;BKl*1dOSR%XpwbIwW5 z%$z-Epa1@Cf(Tie)rXM6S7~_Y{N4mRS0tm~8DD;6`$lktnL8%b!PD?P;ET)kR4Yzt za@z1mU;(lFz{PYhHs`QPc^l=N8u}MY&J&SE#S;EK5HM;V5wC7;L~t=7N#SpmsHI1E z;&fjK5T6pRF73$uFb&j|PM$`D;V_KpNo7-WxQW4DI=;k%GfsTeCV%apS+~+cVc#?- zR@YZ}-BV&>2MuWKXZ@bcQzeDH&6=#LuJbDy>%O0ajVi~I9_Pn5Xh=9bV0FqWn)_^I zHhf7Y7Bi3V{%vSVIVAUo`44Kp5hU#d0RuB<|7X>7sjHFKjX(M{rj!_0hSi>=YFK#G zG8h$EJjv8PlcGpg-TrdGrPJM11ebw%oDQ34q*Va=(Z1RB@xcLvQf7l zX-UjmG>N)7SM=s3uZX$AlFPYb+9{;7WKI-_3UMMt(2NJmDzFWYO2DTk`>ecb5kpSJ zn-)I&GXcayw!sG>VH%7|(Jy10#;OdyrO;OB#3z@c3}aX{w2eG&-KXyMJ zPybQ*GHF_?gc6&!mSy7P989~6r&C;C{`|Yqmf~v@yJee24YQnzev&Eyvk@7uR=J2r zv7)b)XJL~p!V90C!msL##e+$hxC=_nTdJ(&BG8wC;8&;MA3@U-!6IXeMqB5w3WoE;glR`$nykFC3!HmE4JS+W>qoLS!`XN^?=!11Huo%96lOQd(tT@CkBE=w5Q>wy%XuC+z zwtHRS$H2|IW;?qyPE5rUubwT0(3?$=T+O<^6{pZg?P3V&iQABzY7q%gIDjNA?EEC? z?ela6H$VZ)2|)G>mDpF+9T$#nbnsjK4y#x(D?>^}xDaoix&jT+q>0!2ll_t9VZKed zJj|s(0Hp8T#19H2GzEWu1MfdY%x^Xs0-|HJ7zfzE<2bFhO|OuGfj*`GGZD=!N3$w z9(1pe`o%}#v%(Q9|5a~l1Ctz(v0by%oUxRI9Fwg1J>6%;Uy3e6#vzm&E592;@)cD?oT^~G zH>QBO{f)-)yjBEx9D$hJ1f`UN!uW3)N^#JMA5LOq`eW?>E}VD5kmO-xetOBF@%bGM z4)pZsYtUWSe@fhCZ2~Z}T)H1$YAQGU^LtOhdTX@2-+2HAIFP*%48Z(U&L~X9Rzbpn zq(x)UjB$zS=-H*AMDfgfE1sv)(hI&r9uta)_h5ZWTSny7=5^OJXl1N^A!3=ZtP0{e>*rZ@0x?-W2USUTbqLvx&J4Vrq-#to64Rp1BJd;cTBrN)h7x77 zzO`7YYh3TBX*uiM)MR>5NA zODQJ@h*Cy<#%&jm_d|mxqA~rA$y)meoYwh189m|1W-7Z~3SGxY9QYpe_mp?f!^e2g zNkj+J#W0xi^%gflBkNFEf611g#ajoQDtm}D^*>BZ@|!ADl?u@G@#}Z8zQi*9GM&V- z>}^X=nB%U#Oy;r&U2(!=GyP1Tm$B&bbQ|nt5_(8doSEEVXJhs;oonWpzZpDHD=6U^ z5hAvd2BXcZC`wW}rL{E8ZWo54h={=4K<(raTu+~eCt0gi??yUndfp8yd)-I+5^@eH zL=)5zx8|d!d82MS=D#o8Pz-ryxs|u!?Btzm9=Vo>HKkXtsmZ?l#k7<4T2ucK0$730 z{4pkARnw|u2aV??kcM;Ctdu4+T9mIZ`I-G9Fb&cRrC(6U#S9c+CEUZAQwXzv<9Jcv z>b`2^t<4dm2n~2jKD%WmX^voRa2>3!lQW;1sNc&T(v~eWfcaw%{bngj0b|W+rH+;y zv-cDr#uY(pRe}OO?;u$q?oqdqJ6^?&aI8s<-yr~SpVW=p?eAWOk5iXp`GUVCcCw3Z zIriW9q{xz_P{PW-fV%s>+f>tETl@&)R4BOIHjcg=NyY~84FpP_4IzM8PhpJTjMy`P$Dm4M!6V9lRJbh9dSuu;E zo386F zWV4;tUn&E#QP1Ar6g=DpW8N*yw|YpLM{urbU5_qDYEsZF0E6_~9oznt5py2b7 zc!GaHOzHfe#s2WK?DAoK=}V~Y^B*cu52AJvXEdC;wL7!+B#1O5$4sNn<`(2T5_`_x zN{w-w6Ky4ilAa8+efG82;K~G0`2`(ayor4833y0tG)LJK((I(v4~grfzmC$s_Dl?j z3}2%uyT1KCJ?-~yuAUl~G{BuF8O|e{bsz@iw6~V5Ze{rX+dcTp-+sZkrZMA6 z2y+cXSPiH~-kI=K@!#>;W)KeEZW^BcwPjw;%(R^40 z_;sBdD{gCp%}L6`j69D0yMr#~-*y)51VFVV8s`JK&tuy7s(%ZlW0wv~*S$O{>^}(z zk*u1BX#u{;*NBfFpJpB>lIm1<@yyqZ%WAu7R&NJ`U}2qpqc9>S5u%IHbcwnoy%IJw6pWI1P9mjzrG>-~+k|6N36>fQC(0e9$5|iglJ`I* zLC?BWi*jkoWvnwCx13m$4?7=*Ba39RK+19*O?rV6`x)<#i@mix%BOm+xAaX^ z(NHOhjh>7OFvYOWKg6Qtg@vwcMEu5X-AN;{eaYIvL^X_Pyk`Y55!YufVG(6$cHt$| z;h?Qd)K|PBTBSv;y05RBZZuK8)-a@7)sel3oQv9#=8y7f8!0~>b7ATLFu}B1vM-sC zULl|CvMjO!lOA^b71FcE3*e7P)vxF0x@R4SjgLgdrnqWRk+n1yY)Fjq##k6m1U8`( zMwnmjFFegz3-vqP{7dfJUg(caQ&nQ-n3XrF8W1s|RGXjaFbehQT*+raPB3{yygx%P zvXTVbcmd#Z9ry7>`1or-l7`?*R2xNXFp~(Tqrh2+u8%XabhciB@zX+1 z9vK4083%0~Wfu+!VQ8EzRoWa)b|xMmdF>i09@o-VjDjy8I~Y<^YT zW!mhK7NyiBqed8~Ya-~|BGPvpUphI*jMCqnb&a9~PlfJq40z&u#Zpc6e*@izJK)7y z(Tp3WJIIK2d4HF|ZS0b%w<}=SM=>cTaT6)s_9`mI?+;k9HrJQHvHDw}&SyL`jsa&@ zmR43c7iF?sL?LqJG8o(7OZc~YP}q2l_EZP$peQOLakq@2Mx*lmEe^u~zB8M$mFl`o z)b}{SB&fh`VhO9pvtJcfW#Q-!HI)uuWKfW1xnQ>oKs5&?R~PMz`36{^A5uMk3m3a| zNA_EWCdrX3?SdVD%1O4it};P#-o{gbUwJ1}6fyN}d4G)uGw2BAMgsX!`o;1fC59=H zcIVa~8`$F#S|iadbT07WuFTKh@Rn+z3+JZvn`O2GGk?p!$0<26laRc}r+!VQid#_Z zh^rmvE%Ko@7W{sze5>H4yQ9Yn$N>%U?`^d}Cag`GAYc_)JTX723_#Z>U zZz6S>i!Fle4`f9rH;nn(mo%bHCp@S=iQL3Naxco9#BAfc$vc|Hb&5jg+s98C{hL=Y ztfgcq3FuMFf6A?vVM^sFf{4>DS{R;7Q``&>g}8)y@BA=F{DEUlaf&9-bI>=F8u*ZM zhyoBds^f~vbTMhJu6F`> zH1*nlx8E2B#MxndCFx?9PwSm~??0e>8KGP%NJvz3zQ<&f#yFHxkab>!-dI63LwY`GW3r6QeVERMLw{3U)^h1tIj{Yr>^TEm07xu>eeI2nVNx#gEnQFqy{6b{fSS8k9v0C43A4NX#XE&u1NW~VK-%LsOe^aQ5Gj?)9toUcwAH^DHhxE%p zxgz^m=7|R5eaZDXEKm7*#CuSQ&5rn7RY-Nl05aJ@*{T471BPNi$a}d-9aPk;Q)-@W z3P7{g#E*2YD$ox%B}}A8a)#1MsiY9W)+T~2=Po|K%-E=D#F8o*4}e;EAn7)HhaeD2 znYP*iahYSuZ{ldDy5o<92NkL3Qu0h~NNV=IH4m2_L3uNwkalK`#b)vnAaQ0_)I-&u zFuZVLHivvEMMu90QzY&i14krXRYOH2iWI_|o$_jsQ!V49ObU!^s_Ov}EwV zFZi!WmHwDEiOuuov9Rp5lE{>VOdYHTJH?3LZk{U63H*|?S42DDHt#-qG7B#l9M3MB zf~Zf~Vhai4Y8l|(I8O#A?>~g_RHJgaku0`{6;k`}b9s@`#AToZw%0#Mm%iWC?klt` z(jO|0QzW$_5;xXTJ0RtVY@=&(C!%YM8G8}y-~E)%W9{p~i;PE5uD)r#iY+2WV(A?~ zw;0U%SwiUbV3f|bTC9scqhz~QWu@VU?ak!e%4eDou|EnEJ$g=8_K{^cN;U;NWm`A> zsK3b~ay{x@x00tQDw=qBhqzPiBNu>l#@Z$Iq4CNwN$+a0LPRVRt zT|C(;Dl&R7UA!DQW_KQSL5Eq@F)^n2Q)~0b|Goe}7{yjo=`?4IJ1C03m$uj8C5nkEO#%<}f2Ku=EJEqR_&a-R3hiy;C>BC+T;W&qsM@Acr_r~kPaCA) zMn;z}1Owym$j|w9ZHIp(y6evF_^G;CR&$($ z;D)P`wLz6sGtFM@RR^9yM(8)Z1A<)(;?OAp{P1R)Ju3;#$|J2L-roboxw3N@?3@IW zxS5&xF9QKFbX|Uq`DKLa)K))*)wELgh1Fy-4}=pfGxwO<8DyW4)9DKH6lY!N9}*J! zim9g%G00*R60T?}fdZr(i)gALx(yej~u{xb7Gt7e9U@0xxYB?1TAjy7z zvIT4OJw2yzXNw5Vky%AbYt+bvKqfPQ^jzvU4(MgYtS3$Ce8XH=c@}0i2q>8J+GXNb zkmbo?r1r!zVd)bE5OM;XAhy@W#-M0sxHpNc8up75!rD&KOpz+V%-fOH$qxFQ*v`52 zJvR4Sv;g(y@~*ByUQad5u-^JPz_(!hC>3nXJ!UAEbYy$-pzt1Ta*hBqZO!!-TGdyWBf2$jPjcc_nM$ z%T!|Y?+eFcik6V}_*C|enTSplm<2K+bf1iAsuQRaNQx?1Ysv6(lvJK-{&X;jc!GcQ zl$q51~I(9O7t?iV=X*>!VVXjOC)j- zK6RyRzdt@oPdW|4(Zh2Z<31$Aka;9@btxg)4_&o%=nTRR1CQjACXVj`J++V;+9qKf zvm8dfgW>>A$PYAGLSvRA=B-Sk`eoUklDA{!+f|zi@WKEQyd3`G$FgdN3>Q=QC?i&g zN_wrh%vR0Jua^5X_gD@F^zTF6Ab}5yXDqQu!=}oU>rLIM?tSHV(PPQ+$$X?OL_>tH zN9Uc9I%zkq1IPFCQ8HVclb;Mv08Q{7O42X4CXv^lx93~C0^g>V-;RM;+1SSHib);d z-co?kgsE}s-q_sMmVaM_$yr+qT54F%U0;u+wT4?#B-I_$TIJ~b2&wB+>{1m9#=s)&_+i(S`(D*QKgH_=!&kDBG41KPbGHAoDKA91D+02Z!Y#k zZV$ZLRX3e)fh4E24XFwlqdPxyLCtl5Az*t+pJ!;u`{LFHap7!Z2}FAbE4FJTKr{fK zv2ptAYkueDw_dZjaFFCKwE~$;XP^w7rezF4rJ{mhU%UIYo&7TfN6W!6`i7?A87wbz zJd7Es`6|3ASlD5}J(e>X8#+EYH*qh{+45}2x=Vcgh@+Sg*$g6ZIinM{{ zU!8s({IRHy`iuWc)K%pEsaBXzNh*d-Q+X-~Q37pU0!w61*L7ZTLcbYbXmu*z6yL9`H5xkx+_`uVjOc9Kvn9y-JmBli zSAG&Nv7IYj(WR~K##~NUX13tL$o9QZqU3I~hFE6YScX=L-ciA=u6GAe2Awx)b->C@ z#lxHV)RamR66E>~_AjnM58^O}`Tnucyw)nz&UnrLu#(keLlHsdim) zocLAUbiI0S-E9PIG&Du1R%`}z!O*as#_tKNV2F5Pk|4w4i$nCLR%e_p%>L@<;|#^59VJI z_(v!w;Y%*WQwdu==@XbEaOqFOx#iBtx1=0eK?#mPz5jPedap8$SW9;-`VlHF?aruh zf8}Hew%rqRJhtVT^dP$Z&uITVKSnSi#;h9kfk#&vSmr^mZ@XTUG<7=#>fJS5S{{rH zCB;40`#*=Sg>C{C)`x92$B1KZ_O?9*bEdN1n;eZIXrKJ-2uKu3oAAtIk2KLdEc~CM z|NE2vQ`64>t;tX+V0ZMBvQ4y`BcvpdoQ130M83L?rN%ml(ZF&9W$Ib0XiSuOWkKXH zsg?a?k;+K{Di}wdHU2b{m68iA&ztGyn7oJTk%f!nI{x);;4c>eIQeu zr4ql&*^MmX*|RCjr;&&*$JLZ<&|zIt{VC6V2o=HOpNWP3TvL#jc>NrSpqF&AbgdR+ z^k|V7GZGq{A6hA>;pKdMeD4C{9IbI+>w2BQm;LKxNd49D#>6pqdH3y9_rfj)8l6V4 z49Uk8k8oKLu5M%*M0NFmbi`rO%d%@JjriBUFBq3yD?*L&E-p<;*CnE>acpg`-8NCc z5mXhXw8h>Jhae2@K9m7_EX%tb<4L#KN%gO~KSz_AwGDWV?$t#k%bVkerhNTPA;qp7 zItI_rZCXzhO#Cq}Dwj8@t?a#AgZk>lQzWtt8IIMwHfSt1*f}ITDJs8sgPYxUSg6Z! z|6!Z;LVjOw*-gxop(U<79ho7A^GmYw%T)cZ>Divxe_zNf@V8^O#m0RFC`Uff=`3;{ zJ@OdrZ~o=3V&Y#LK^58=h-$i`ul(M+;)K+km?)uL9qD>?n6cT^NIJUIQB+F4nqGet zvpXod8(%ssG*MVw{4Rgvo+p>LsVp)kze9X05m}jdqt5iwUrlLI`yD`VzU=s+M1(MP zJ8qJdnmw06{s~QAj2#Adau;~kBjG3298;(O#8WR*_NVM}zHOh;66EBXCiUm=E;iP-;jF02wWvaMwK>(C%f{ z<`D>_xLj#qZia%19V42P2OUhZV6f&X1*?r}HZ1-3g{9BJbyAbT+WFTvThfGKLyNuF zlOF%+BuS_UG=yuoEFb4VHc5WFCBu7xKmQfX%~^6gteE8HO#qGrzUeui;l~LLfqSIl zj^YpI(wiW5|BrELn&d{d%cP>isR0c)O}6(mu%?Ik=YFjIYC5T~>h>DN zxGK*9G^~j6WUk z8vsH|UNHLAMzoxevVCi4dlC`ZTmo?z8mhZwH(112Unbnv;6mCeMW*7F3CE*AkZA%1 zFMnN>r$e0QJ(){hEZ+D6KTb+;Rd1z8L*TzJrb49XkvI=nFO265Zmnsh&9W-^y$M;` z?GPnqU!!wvk8aPk2C?mz#1}29g|(A3dt)o-dkMzL%)F)Q zh`00FE&gzsyNN{ID>kt^VykSXZK3HqN;W;;4_Okj-q$1y{K-3NFPjq?V|He?m>L*l zdCA{I$(0wn-5Ep_e#cHi^}|h`;*0n75e*w+Q}fDp37Aj$hY1`--D!VDCQyNT4Iu*u z|7#zf$MOGX9|VDFEm*SqRZ{`nr$%`FmPzP!k?$+pCfbu^8tKSX6g!&7w8BZ-AM9AE zi&keo`Z81byYR*Dyq}b<0JebKh?b)3huF=(FfNUq23G}LC=#=m5WLN`H!y9eX9_D? zD9YRId|0!gv0ugdbxOS5&yRz)lRi;arue6f~)B>4PxaEYY7qwLxGLwL!!B|n~& z_H1^6A$|Y+gX8{^bkAM>c?Qx>^O`@9peYzo>?jy`&wC^spK~%NN~#%s8X_=;7PB?G z_*b)-u=tMrB}d?QC75SQr|3&3)axrvscspQ6XK-)cHc7{jY(G~)~ca~7Vt>LDbZY*YT z%e9V+8I(`%^wbbmVIh;Mkmb)EA@cN5$Mv11{l4eK5SkcA4Ls(joWU5#ksoGQeWi+m;(4aqHq)ynARKDxczF&+r!ODp7 zE+V}R8WhtKM1mU@1J<=-;IqnqdCyJ}sMi(9Zn87oL495N1oWC&A$G%BAdBT!i>--v zCMMcPQu5zM!DxYJPTtJ=grW%qABwmVHDW4z6I)Ja4`g!ncikfgu;e1>Oc^P*`CW%Z z`rV(>~1KNw7|R*_Yq<^2zLj@bhsiG>kRjF0`QSb$iXVBEla^O(5z6`vay-M zvA;H=Scg<=;68UUk=Wa?0aD2f9kLhFmPyH_j(0Tvi)Q(i9D3Z2k-#;o@5p5>mZLT2 zrJUpI3)JB+S&YqlD~j7B8=>UGz17woFf%HGGZ*0=gmqd}CBx*@og{@F*J`XFXq!Y| zBmJif{p5m~i`s82V^llVs_{fN?&lTUL2Ba1D~GRZ^IZL7klMM}?KNR_ISTGm#)Z%{@PMJrXK=#wBJ*EgOB=lH z!)0YzD3pn(KS9Z4!#^i4W`zBhGmsOF9p9RjxbqqJ;3Jzz@4ULrPxOZ*FAM$SCoJX! zU@l-GS*{MOgO~`_I2PP~7s-(be-qA9w6%)b--^W0lGA37!?_pE-7CV-#$l@%UHm&| zzgAQi<|izsGzs?14!|X&TL?GILMtYE{?X84Y3G z1r20`Ttrpb!pCx1FWQN7*Dde#mLbq+HJNK)F732JbVCN#4Mi0OCRA3&QEn?$qu$st zmZeSEfmMl?QRMyYy+iT7T>Q=(H#aBQk@7f^k%D+^B2V!UUA|l_D@*Oho~c4+H)Gvd zL!G?sN#;(HW`kR>@3ASel@}OL3FB91{~K>V+Pc4nPAr2rELE&(7^nUa>3!k<@ZV@~;UF2K9j1tHB7 z$x#4}b`qw14|;(;#{o0~dDwpX@GQ-q`qW&Ru3j-vN-$3!V53Q-Rwu95c=7LxK#ywJ zJha(aYPU4ud=9#9gnQ4}cp~&U`FYCxsS9U>_6LRPHs zWsDL$8?{eX>D$(7TS2Jyi+5GK%-kAnj^p<$#n1H&VU?D)MDJY^k_Y!+TQtkKTYWZG zi|@nJ45%Sh;@=1&NT*u3Blbc?f~J>rN?v>ergc(+Vw8cAXnmyU2C5VrU{c4?uZ_$e zp_oJ^fXWynbO&6cfd;(h(PiN6G)S?8%?bFBfE;Y*r+*_p94mMRj`nzp6*rGp^pe;@ zG;G@&_??Bw-|}v`n9CeR^fpni2T~_)YJNWK&dHj2qJ>PK=s4{4F(wwX*i&F{3?IUq z@TSqUlulNO($p2;nhbIb41>WnpXNgW2FsgCBsX-STdJ=(hfVMm-fVvkP#s1Y^*{~+ z5;@24fs%zHOv|6|U7Tqw+t*a9?>;6PW(pE!w#vKZY)?7zvIcf}B~iSm(j*?ugHf9^ zxr0~qDnfkX_DB{jT8Fs;cWctUh~FOl=h*!eZ-aizb*c$dXEy( z#;{7Tc5rklzS6Gz&(xeF+2wYjjqZaJJl!V!TfRF?E6mv+sl@7KF>g$NK3$aoY6+PCt zS)ln``e>=?IwNP49hr+fD=&i7C08`f87JxfeU-j6yY{miHRJe*O|;=Jd9;2_BoMB# z!8k}pvo9yR-sgu7XPoP+I2g56(n(Lvxs!|1G!VgFN>{|8;h@Up*zZ9jkf93`rcYzj zRa{JDS@H2?Rn-cibZG%R4<4~!7cWZqMBP$aS?9vmDgGQ-jz5=;4OAt z3tMU%GgyM_7J-CJzYK5(iQ*Pl6zY<7i6qSWoan+?Jv#|CJWEF!Wh;6!RRpcAZe*&F z6&4c~Hd|-c`1|}?Z}z&>vlBRYbBOM)=y%vPjg{6|NTGxstz-bcgApc%JQfRHu2|b%dzcXjC z{q&TYlD8;)0&swB=eA~2>U%5d$^Scx%TuiQw3WzHUgUk$ekVw6jN5|h!&R8r zN2z~GT47QlF_)Kul=2oX^hOm;G3o`GMlmr?>=|>BYJdP(9|+$|JZ4%ZvOV(czW#|P z9>d_f%~ZOQ26<~cZH=?CRtu68k{e2=U#F5ET#V*%;#$q;h2#Exfh7|6C&l+JYB{Yh zQS7rzxFZ5;T994S?`VN!*w+F?63!va)rq8Lw4-@m=@4{w_GWa}#?Tjk1%zN?o)b{7+dya5lD=zx;e)E{6)x48X6akQu_tY?^ENYkG_qPPx90WK_q zZ$o%!sZrWjB9GXTXYJJ=Bl@ijGtbJbV7j6Uhmaw-BoWzUNPAw|8u=*{#%2 z)sF)DA8i7#{%}hvYHticv*^mx%%aCDuyb5r7W?_fD)Nqpjj2VRSm_m3Vr5GcEFUPA z$SDqY(>%RRJ2F9jPf|Zxyxr=OefI7Tfj7*+oKCHP-6I$FcI*8OqOh>+Gy^mD&xUe3 z8zlhdITsXfF5J70XGVIjDM5M426`_@s}b90sK|Q4kg7pFA}_ry6IwGU8uzzoO}Gz8 zEsg=ap-4|&79jBmNWh&}SyMP!y%$^-5~2vL`W;~-<7cIiJM#CX(H{qSpXAxU3GeeF zy+!@+#A1nHvV~A1_~>iR4k^brk!GmooMXe%m)h#<`CX&lU$!tp$rI+kiqByRA%pqn z%zt73zF-I${Udc2zK=1E|C#v7>faYx=Ls_9M^~)vs^cy`%=u+YzqV?35$8KUEm$nu z{(WIF%ZLnJE3QyJJnf3VD>Ms_)@)nnj)cOoA zKrI~6&yxl><#WVg$Ri)@)UBuJoybbVbm_H+vgoZ)PgAnd?_N-wpex?0F0A)xfM~)%uIo269QTa;nBy2Y?+FUs!6W zrwJ9eAb}ixktgnySR)W!@)#a$b$f2`_b7a7CsX{HR5;$}DVW32L$X8r&YS6f)Y8kZ zphR1oE{ewsc$`w)XcZPzq^46j%($L(Q>Dd%giQ%$Sd@67B|K8=s$J1IEGx3c># zdJc1^cVF6kyrC?SGw(zkk64Ok zO&;}NQm_Qu=_(|l@fO>!stqfp4a2_|+e13jW`r3BbJ>f>6fDlvqas;6sLFUI-Kkcn zvW*5Ks(3jNR?eN2LL4^sien5gV>RhG7Q0le(*kc9B555*CeToF2fG+SMay1zMA~32 zWwWcS$(o0~J5@B#s0US8ga4^vL#s5l`_hHus}vBpYpIqGst5Hj*~g7ETGDoyCJbG; zX5OWq-{Ga#XZ)xQN22!Zni3Bagk7c;+Ob52w4n4hmY-t3Dm=X;he&CoGrJ({fe`G? zCS|46+$ed+DIz5M8#V34(3PU8o<9^G-ge?MXKC=CVpwW27BHc#NkwnHrP5gHIJ-v- zC)_A6vVx>srQE{juu7FiC4C>3dTYES`W8g&wM<(yF<9zd5s~PbN^euvM>d}0hE&Pg zav8T)Kj7h3m>9uzLI7Z?0w3|79jSk=3OKVw89t|lqovSZ>^ zVnDm`BP?_03DR!+b!qlkO;Q0|^6pry8jr)p z(MqOr_cG_`t5=Gco3lEGj3+g*3%{6br>SuXYcdhdi;X~rTbWK7!$s&z=dCCT=J<-y z5|};3qg_8->=-n$1KODiADLxt*miEf>d(E!^=I~3t)-?)$F=n;DcdDkPkD@RPNgYoS7d;gp%GV zT4gp|2vcZCUicnj6~jg%6?@=IseGUy3(4+R9z72rwWV-Tow%aGO;q82bx+hCb}t{^ z6ZH(=T-y_d`784DO-Q(&iVokodvsHM{t?am?eRM+Y|?X@)t=bxpmen4zHKmppt@kH z%-mfY)0GOh3YSRLn|YtRf#HuJjxQQQo2#@>Bn7H@DhvhLV4;AAR_$tHYOgsx1$>ES zDZ9ho8m$zcz{*kACXvr+;Y2W&%E)L*_e$@}kyvcn?%9fr*|?{JvlRp_*UvN&&-@beR^f7Zjk_vcCZn9D@>z6*K9ai;j4~z6%q2tro^j zE=g^fY`4Oj66%@3-$Mpc(k}O8I6L{4)4NmsQ58dDB32+XY5lhJOe<-Kd1@Y}p55uC z0|iqdQKT3V#LmmjPV2~0+R?aK@u%zX9!z$KcnJiWL-f4lA8ONEQanR!5UeXfn-DBy zM8B>ou4n><+B(bqD%(@Fh(v>oSiZDd1z-gXgT4Ek^*qMN4K2zt6Fb~$YrFVi1@*c1 zSSse2FSVJBtr;pqb0swmHb@$&xrkfBn6$KqA#A8;z)>TqvT_&B6+fTrob?XC#>%|f z4N7yOZcI?T-wEOI-&{%A(eQu1b;J61WdR0KA|jZ#jP)@r%3u*VfMZ6!`RxKZAz?a8 z+6+w)Y(j;?xiVr&E!C%ge?nJR1E6(W$r0RdM(_9SDm&A%K^HMDttc_b8Nz&yem=0T zR<-9G)EF(>Jg2DkTkng7lTYD>^x{Pbfy%kmv#G#qGRKlz#f~a`zQ;Q)Q@*MwG_u-C zN2ot5u#hA*F*0|`mW1kXn~{ zIgaWo82#y_FC_m@$U2DLj1y%qnBYOYAnAO@upVCmUH_jkLZ3H zy)T{hVw%m%@Y>ZPlcqP50e`pb&nC@w!+u#pNdYM$gHZcQrWt<%^yAuuh+5~a9MxC> zY9-^ZY21mPrM20&XER230QlKM%GIOl_u+8 zvI#GTFFngP$k?-eAIzZO-2VBFpzU5j#={h+F06lfwk?~rVIf93knb&t-8vQwjQqHV zD^n3PtlA6U zX0A3)vNoDjcu!>BY`NP{(OmN$#zFfw9P!(Vg+< zeG)bC5y_8^Sm)Je+(!Rkw^y`0V!ZFonkyEm=wIRs_k*5T7hzYPh)hPyDZLzTFCK?n z@|@R(E4yNQw#ZZLs*aY01-cY7>YA6 z&LZ<4VgVfX)U`ww_lDjA3ju&Oj{xs6aPiGUt#qao>!Z6Ob_H`C#*YIrJ&TTltoN7K zA(7hhGT%gIA}B#W_+A%pPwuZErT_D+9NBJa3Hmmltv;d8ps^|y#x}4 zLOyMxX$d6O;XaKlJ8};S;q|;CGVE%MDyy$Vmk4`zi3~-LhW6ni8U>N`pcR>l)xpz| z)8FWWs4JRvUGw0nqvPZL50ye9SC16$_Mx=GxeY27FgD9l(<&@rWEoB%{I%P8P5A^*mX&lO|rckcYN@1VfoW3D8Y*UmL5m zD*|~OUSXanT#AJUF_&DDR#Z+P)RayaiFah={vIS-0ap{8c$vkipZ9ubj6KidL``l> z@9$8fSd=D=Kf1GE_ew|SJErs;zPSLSPU-H3q3X}26elevTQ^-y$e8ssQ700l(25ml zA|F^qG&k=>@vIa~a^D;~P?Xlkon&|NZgMSx2}3%9sJ~zMNY%45&@fc5Xe|5OJ}}4S|q(howI5jk&`WT^wunq2ZMVu<#wdO&%akgSiD@ak|?&S*!J0aI_gT9y^ye zM9FBp<~a{jI_XH&J9M6FAR&-GOWvBBe-5QavG!Y~Z@)GyuV&`M_d@rnXE+Fh3W9xFBJ#Cd)?Dq{9{eSTWYkE zZT+%Ws>IR1YjB@i<+DH;iOScVL**f!0PsZdfL%+?vu;W`NRLYBrzzj#@8{0feUw~(z8=rlWSU_k(B$|xezGWF4cN(Xy_oSiipjN|BCsG1D0sg1 z|NA8edyg4QH}s%(wl`~GawQkd-M!x!xxmE6BkCr6=ml_w9(_FQtuGCIrKBUKg=}1~ zrxA5-vGk9~kb{*6(8*XdIVv9!lc;++whPNXr>{mjcKUIcHGLPOews(HB{&yv_K7eD zF`DdA+v=2QE_hM<`;YnZb?$G977MV$A z%8im!Y4%JV%I-$xEgfZiF0zI#h0-kX8xiNgzhSIaPBBCZ(z#*Tl`WQ@z}5szmg<)m zV9HMDQy~|$#$KKA+v96y=7Y|Tc=9x?hDTwm#^5+X%dXJ`voOs21@4_@&9?6$ebx0* zIbZ0L@K#HSNt!=hQx2vEij9G1IJ^hNPl=f$r^}8YC8KU693mCto*$OS+kNQ0jLN2} zPZ8P=4T)K}#8IWKyn|!kof)moDZVH;_~YpSh|y{Z`R*w*m{b}G9<^D4XGC>skbO{D zJOA~dHznd@B$hWAMPw1Eub!XCANCEM>aUHDO$bi@e?O=Yod0gG@}KwY`L9rtIBA;M zBunWl|AS~wK`Jtv47QdKGI`Hsr~1+$)auW)lw5bhF#B=n&%Q@%CeTHFl$jQ70IWG9 zterGJ%hdx%3bW(=tNssF?;X`d_l1p43MBM|8hS!kTIfZQ6sjOnEMOy4qat0ZNE#5N zHw6_4O+XPr5m8YS2vt--L_|cIh$vMAq`f!4@4NSpyJj*gYi8DIbIv~JJbUkF2Rdcj z;AalgBXgBfw*<9MljEE;`+m5L%W&`NRH6Ptb|lie&#C{7RrJ=VyZ$#|#&Lp*seOiH zJrzwoxHy)&@8yQ&meu(a^aQsd$GlU-NB1c_0>E{vsqvIfp~MX3JJMv!%!<0uchz3Q zR|MsJAAK8hRH>UMkm_?o?Qx$6UFPywE)8ZQ)zBXIlk_)^_IS*PTD4q#s0`%hm1cXH ziC^*m=lrjZ_e;P2JE>>2^h3_d5RVpVuhd{y+VpYMmuLHp&fa(A-JiCu<|ZCpv7URX zQp&<}c-4Tl1*0-TkNv?|NI(BPzW-ieg7e^*-;P z@o^(4V@*;7W zBiDdz-Jd}*l@bmJs3`6nThu>VAdlQajOk4e9!lT!a!y&$T ziXO^bs+XQitb^(HZ)BD2g1QvQD|+bfovP_}s>rVXX=JA=(lYZz#}7sAl^pWlqwMp~prr zA6V&yxv({}lkA{q29D&!Q=*%>{qIF(dj;uZU_XlaGEMyrvjfP&<;M(E6be+L2hH#k zBXE}-)2z#e5@eBM z3CaVr=F?df^FdiZVao0$e^7fA34X=UHD%&lSl8clu5#FTTnr0~JZz+syCh+1)C|FP zIh-wX)RR!zv0sat`WAZ)qg!^a1Ql6vJPFej5ZAan*{m7l%hw>P-VowdBFgz^_yI8^ z@I`Ss>bvt$O&Y${rTez+D1^*$Ramj54quexjBE6V(RDW9*8LcpJeX)7lAY`}bv&Ci z2?tugvo93Y9L5-lbQkB&3CmBUqUuqFx&H)7qkKQ-R=OcVVY;0q%_=@A>0 z%BSeh?FLLd_z{cyXXOJMhkxYDPe`^bfvRgBH=Ew?=F_MLdl~}({dfn$n*z4y9E9T9 zLKMH&q^>|KE3Wa&0`b)Y7lt$@dZ5HuK*{XZ)zk6GqU!I-Z)Pkb|GoSVz%e_nb}_fy zVV|&Wa`xQB$9ogUM3Di2AwLX(HmLO3`>{=RHMfI<`myF)-d}97-`~`iGuMy$w0G1@uEQUoh%wn35pV?qTkG~FsrD=o_fnzk($diRoNnXE0;qS z>(&0XV}zSX^vL=Zw%2~{;jjNmAh#~%!T+_l#jN>{lz!d-3;QFRXx>t37(d|87>-?(RaNCiyuRZD^C26`-}T-2&~eyYu2<8V_@8XuuXMWhsO z{T2sMKwR^lMav5XzL6B3^N=3-gEVO_AVr{n(NO^SceM-3u2Y;`M;CJ1MMdti-IoFgQ;fW=$LOB%pk zibNA@0@mj((Lqg$v*Bi1YL3Fhh*sd`eaMBrUIpP^)(gxyMZTuUWsN}et^*zFM)as( zT^Kv|$b_N1nhCuW?)>+Ey&G53-lIQv^zHTYPhAGxN_v$)Px*I06+K#8lz%j@ zrsI=5J{(j%P+H3in3OiBq$_78*I`8yk)2>s+GLvyU-Dx(Li%UF#9R}hk6Ul*H_Z?g ztYEwq1inj|m}yr>aA;c`5Yo0({;mp6%g3pty^nKT9KAa7wDrB$6MGBH9pQ0 zWqXdLKME6P3OijuVS>vfxCiVNTtBuBt`*)cK8|q5kE441Ds06~=+#n;?N(0UfE^!a zJ2m2}q~;$z@fD{57Sa4283{)npN+logrLRQ6tJr)0 zhR}REwA?}!c^xLzq3efu`*O=il=6_)Md7?mrg;V-c}6TPJ;`ieBrE%@p_wB8Da2t* zr*<)iiOb&ZHe4ns*M~6xO7SMYgRYHe4r^7a2x|N54Z87RNbLTKAm5lS ze>JxiL$Nyd6;J~V$sqBt)$`-gFJWxcIjG35Ca6CNj0QoE=X6`5!WWdB{{2uMn%R#+@`%!6c({#319>D zY>f9eY)M_qsm_X+IEd>X)Lf>7en%VDVL*~zwP1D{^qQ!xI|1NSvP(JuFx32(l0BKn zWrVi>UNlQm@MGI-P6@%zdSqd7!Da$a9))>ef>lfz_P9%mmU4n>mn{tz%aMP5o6{^B znZ!JP^gm>)lR0EB+v3(--VVmrg*$U~Af9wV#D0FqcJP%SH|mMf>(7x=^!Oj#PLUJz z?O&fpx2(Q>+bXXW_FzX-KVVn{)Zestd%=O=NzwGBih;SGDi0<@Mkua`^3J-;VrMW< zFc$RoIOb&w-?f;O4>ESI`(B(s*V|-A_mp#Z>%}e~Z}|PB2Qiva(AHEVeDlTA)radL zRkMK>KX~)w8c*+tlln3rwkuYV33+`|LD7&73ln|(EVzgbG`+5^lUv+r?K&-oDVLY8 zay@qb=!SHY;3Ml9wOFN+>2-zzlwPQu!v!vcSXZ|iTMmFHF4{DjqvWlsD+3%(jM%t? zF0}N%x(m*!c$T!x&aa2j79yJ#S`W^(^PDoG5Wh@{J~E^9WG11e&Yw$9ThEJ9K%yq^ zZB#p29zW0uQ-`y#2*_EVHs^EE$xpES#3Y}r(F=r2tCWyLvhnG}P*b?=GN8LnxF*+P3|)Lg;drN33!6PvmmO1{SqT<=J-N1H9u#`JSp;<;SJFW8EFrB z9i)d;3!ng5L4Z%{f*$m}J90}xu|sT0RXE5r^qGEB?f$z$SHQPGq{>FXU)!Ah#*yXv z{`JnlURTW4(D~|;dh34PM_n8H-*rTBB`se%f484pFa*3**W=s)_KZ1Y# zI<+gJ+&K3rXE1x8_huf{{}P|g!LGN1vTZzYXq4{vWH~H6{?LeTR zjy%Pq-)My~kBF;x+cMirp9^b6t?-SD_E;907~gaqg9f%M7!-<%qqO`xjm%w_?{_oo z5@x#X@;wMqsizQ1HlGwBF=rbj!2ba;Aj*Hh3jYk2W03+C#kh7@c<&(^)I8D#Oluw@ zQtGCk$>8qzPY_RkrgG?NbF6(+WN7Q(*_-vjQgAG_lcI@{nSaV{SC=T($5 z@)N4bZ-#&=L67KtI3SsUHW*c2pvWLJMXn8AwC;rj-@Yi1AeNkZS3avyueAUuhkP&n zy~3MR+`6_tDcgVSQvQ&jJm@A+>|+H|fs12lz$FV!wb_)9N^tQsh}Y-8^ps&kBDc~k z8B!k%srj4Ez=c3AxvTo31q}6~bk%YBK@pNB@RwpK z=9y6v@R#kY;%b{NyT(4uk-2{9%bFuA&!;`!$Tc6WC`=H!Xtv5Yahk3AsXpi0x1H0w zzq0;rM=tcQ@#KQ}-qV3y{feL7#NG3<|6BYCjhqSmzso>zO`P3(4X?9E5y->mkbcAv zJU)6~r-pB!rHb-TMm-Q%eRXM0)&8}oxC??;Ia}H9Yq}=3ZE(k4pfR;io8Z9?5SmpM z*StrfIH-w32O^&g2n7e_)k?npQ@#CeH|%fAbiodN-eZWt_txtmyN7x$0CEnkay|g` zt)f)5D8-`ZPEpUzI&-;U%sZnnr^WR+^fF-~%TmUIiTRRf;(Cfya&ev}?e-elJCN zaO>o9sQSIXdpQhsl;7Dt4fJo>hbNNHfA^2XPIW9PLKYJy;YPk!?XKEgQsasoiE|C1 zoD{uPCb}cSqW53(omG-3vGFB!G;Mz^mn}=u6%@`v4zL$^(Hv+tayBzd03bFh1;P#} zVdqWglu#!I+85GC{?avmP>WJrymTObto^~j+z+02^|Sb0{q?NB-uBxk``gte%16{ukL$?=AyQMw`)3|#kCf|GskPI*HgmH;e}>` zFRv^vNb@ZS?K`h3KzAoEZC@!9ooDbJR5SEq42}5zD@4d&49xK|xI4#NfL{fIO0`fm!J+LS|HmsJ~F)H z#(LH|NP(pHS?(sj>l6IaWsD&Oa{Oc0c3*!gXhm6hMGzPk>z;*t<9UHE{dvEkU$Gm# z1rg5G0`Zpzq_|i&3Hc0O(dG86WRuL4xh;FyCx<7f-0J{-e+QlSRAnr(*eT3d|9?+C zwzM}Z=WKDCSy`KNIX2XhB++~9YxdY{yC=VuPI@oolV9gxeUAZ5LbqErWYw4LydX_z z6yk8_Pp8g!V&$_YycdK~IXJitSbbvRn)3{)6Z6l(B2~GY{1t%BtA? zZm`TNIn*z$vE`UbKS$yr@pyxBPM`8?9y$0(STcd$3YnOY21G@Ty#4Q4H{T%iapO$O zEXWZ?vjs)34BaL;*{`$KP`4i^z7&e4`iS|&7wzE`_Vu@&Mmbowng7Uq`d86Fg(4A) zsBnSJaCoL(gGbs~XrW@O=K@`9UU6r6#bpXo)Y4p4gR1195)Kle!hxKOc%M%G?PCws zxz9SP8f*^a2?UkNnLZg*K1i`ioszoU{l=t`IuDiux4#jaP)IzT2{N?>G;-ArD2VmY z;NEL_q3r#-?@9&;p(~a*red3kpqA8{9%+{Sy>zfZr7WnhANjv5lK+4s~DzO=o=!J~D za;@6@x{#qmyCgrzt$5{?oN~8<$cZmi)&5cwMb^}we3#|s7fU;o^ZA#2Eh}IJd5)whKe-4%g2gdgTfwIA;|F4RQ~e$vfX4BWHLPH z=|x0Qs^V>s&Sk6vmyer!-u#X=HfbzwL7-K?Y*&B7WX*hwxrIH!)iQ)bh56z6s^ATq zLa0b(x;}<^3F4#wT$~I)ZfqypkNQsLK!`ezSa=z z)S`kIHkYv%82>jH#nAudBI;7gZOsbf^`zOOPx+;X`a=Ux^Fc&?N8`I}$XE!@?MROH=Fa?)jAw|exEiK|BmfICF+g}5PFbks&BEG*ep`yf zka5i-GhqU1APko)MVLHstUhxdjE73vXv$8}@1WNyQvhxTqamUNxd$ra|B#v{00$%j zi*AkrTg1)Q|C4wOZjK300zh9xob6=#S~4Bg{*{RH5*PSi;y`OAM(w(Qs0R9;jNqfH z$Y@stIz9E;G=u|d5?+=F!Z8Z5k^�{qzgmj(h|Fe7+lCO1YN3r)?qDY!ju@J*1e9 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�)sLuHHdCE}_ml2oNK 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 WTXoV~^z-GMcy^ZrTZu>f-S|Iu@nw?$ literal 0 HcmV?d00001 diff --git a/images/pubg/season-stat-27.jpg b/images/pubg/season-stat-27.jpg new file mode 100644 index 0000000000000000000000000000000000000000..a5576c0f8884a1e7642963b02f4dbbe53c6b2627 GIT binary patch literal 20474 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
(心得)Linda-Rising敏捷思維的力量
(技術)透過Github-Action實現CICD-Pipeline
(遊戲)不靠T轉跟完美消除達到TETR的S牌位
(心得)不幸買到七進七出子龍機是什麼體驗
(心得)我的第一台Lubuntu筆電
(技術)大型關係管理Monica
(心得)Linda-Rising敏捷思維的力量
(技術)透過Github-Action實現CICD-Pipeline
(遊戲)不靠T轉跟完美消除達到TETR的S牌位
(心得)不幸買到七進七出子龍機是什麼體驗
(心得)我的第一台Lubuntu筆電
\ No newline at end of file +}
\ No newline at end of file diff --git a/link/index.html b/link/index.html index 7c380fdc..33d6edcf 100644 --- a/link/index.html +++ b/link/index.html @@ -123,7 +123,7 @@ } } detectApple() - })(window)
\ No newline at end of file +}
\ No newline at end of file diff --git a/page/2/index.html b/page/2/index.html index 053f467f..ee1a3cf5 100644 --- a/page/2/index.html +++ b/page/2/index.html @@ -38,7 +38,7 @@ toc: true, rightside: false, } -}
(技術)網頁打包壓縮的好用工具Parcel
(技術)30秒解決Dcard彈跳視窗
(技術)製作自動排程的YoubikeLineBot
(技術)淺談伺服器的授權、驗證
(心得)考取AZ-900心得分享
(技術)大型關係管理Monica
(技術)網頁打包壓縮的好用工具Parcel
(技術)30秒解決Dcard彈跳視窗
(技術)製作自動排程的YoubikeLineBot
(技術)淺談伺服器的授權、驗證
(心得)考取AZ-900心得分享
\ No newline at end of file +}
\ No newline at end of file diff --git a/portfolio/index.html b/portfolio/index.html index c790e9c0..754812b3 100644 --- a/portfolio/index.html +++ b/portfolio/index.html @@ -1,4 +1,4 @@ -portfolio | Boris's Blogs

作品集

開源貢獻

大型開源專案Monica文件翻譯


評論

作品集

開源貢獻

大型開源專案Monica文件翻譯


評論
\ No newline at end of file +}
\ No newline at end of file diff --git a/search.xml b/search.xml index 403de910..531eb339 100644 --- a/search.xml +++ b/search.xml @@ -3,12 +3,31 @@ + + (遊戲)獨自殲滅11名PUBG玩家並吃雞 + + /(%E9%81%8A%E6%88%B2)%E7%8D%A8%E8%87%AA%E6%AE%B2%E6%BB%8511%E5%90%8DPUBG%E7%8E%A9%E5%AE%B6%E4%B8%A6%E5%90%83%E9%9B%9E/ + + (遊戲)獨自殲滅11名PUBG玩家並吃雞

開放免費後,入坑 PUBG 兩個賽季了,對 LITE 沒有的武器感到新奇,Lynx AMR 反器材炮、P90 零後座衝鋒、MG3 異次元火力、Groza 近距步槍之王、Famas 遠距步槍之王、Dragunov 連發栓狙,但我最喜歡的還是 Beryl M762,高居第一位的非空投 DPS 五秒內能秒掉一隊。

超高輸出的代價就是超高後座力,選用補償器 + 水平握把能夠抵銷成 k2 的手感,頭線加上預開,100 等以前玩家隨便虐,策略上來說,採用壓線進圈,比起先進圈。

壓線進圈

優點

  • 抓跑圈仔屁股
  • 不擔心被後面偷襲
  • 槍法夠準滾人頭快

缺點

  • 害怕伏地魔
  • 害怕高位槍線
  • 對投擲物、藥品需求高

像我這種單人組四排的玩家,不太可能像戰隊直接在自閉城獵殺玩家,比較多的是掌握資訊後偷襲,想要一打多的策略是逐一擊破,從高位槍線逐一抓掉,封煙扶人立刻補手榴彈,低段位玩家不擅長使用投擲物,事實上這遊戲的掩體優勢並沒有如此巨大,只要手榴彈丟的夠準,沒掩體也不是大問題。

吃雞

這遊戲七成吃運氣,等待時隊友等級太低直接跳 game (不算戰績),運氣很背沒掩體又被刷出圈只能認了,有一種說法是空投會落在下一個圈內(未經證實),前期遊走在邊線抓人,後期在圈中心當伏地魔,選高地,選掩體,剩下交給時間跟運氣。

]]>
+ + + + + Diary + + + + +
+ + + (技術)Laravel-Queue-訊息隊列 /(%E6%8A%80%E8%A1%93)Laravel-Queue-%E8%A8%8A%E6%81%AF%E9%9A%8A%E5%88%97/ - Laravel Queue 訊息隊列

特性

  • 異步
  • 重試

常見應用

  • 建立、取消訂單
  • 電子郵件
  • webhook
  • 自動付款、退款
  • 每月報表、帳單
  • 圖片、視頻上傳
  • 更新索引

流程

1.設定config/queue.php.env
2.php artisan queue:table / php artisan migrate
3.php artisan make:job <name>
4.啟動 Queue Listener
5.Supervisor / Horizon 監控

介面

  • 單例 ShouldBeUnique
  • 加密 ShouldBeEncrypted

自選

class 屬性優先於指令

1.重試

1
php artisan queue:work --tries 3

2.優先

1
php artisan queue:work --queue

3.超時

1
php artisan queue:work --timeout

4.middleware

1
2
3
4
public function middleware(): array
{
return [new RateLimited];
}

同步 vs 非同步

同步

訂單支付,同步耗時相當久,無法得到即時響應

order1

order2

1
2
3
4
Route::post('/syncApiTest', function () {
$delaySeconds=5;
sleep($delaySeconds);
});

pending

非同步

1.範例需要,不建議在生產環境中的web.php寫邏輯
2.dispatch 成功,會將任務加入驅動,queue:work時在後台執行

1
2
3
Route::post('/asyncApiTest', function () {
ApiDemo::dispatch();
});

jobs

ref

Laravel 消息队列实战
Queues

]]>
+ Laravel Queue 訊息隊列

特性

  • 異步
  • 重試

常見應用

  • 建立、取消訂單
  • 電子郵件
  • webhook
  • 自動付款、退款
  • 每月報表、帳單
  • 圖片、視頻上傳
  • 更新索引

流程

1.設定config/queue.php.env
2.php artisan queue:table / php artisan migrate
3.php artisan make:job <name>
4.啟動 Queue Listener
5.Supervisor / Horizon 監控

介面

  • 單例 ShouldBeUnique
  • 加密 ShouldBeEncrypted

自選

class 屬性優先於指令

1.重試

1
php artisan queue:work --tries 3

2.優先

1
php artisan queue:work --queue

3.超時

1
php artisan queue:work --timeout

4.middleware

1
2
3
4
public function middleware(): array
{
return [new RateLimited];
}

同步 vs 非同步

同步

訂單支付,同步耗時相當久,無法得到即時響應

order1

order2

1
2
3
4
Route::post('/syncApiTest', function () {
$delaySeconds=5;
sleep($delaySeconds);
});

pending

非同步

1.範例需要,不建議在生產環境中的web.php寫邏輯
2.dispatch 成功,會將任務加入驅動,queue:work時在後台執行

1
2
3
Route::post('/asyncApiTest', function () {
ApiDemo::dispatch();
});

jobs

ref

Laravel 消息队列实战
Queues

]]>
@@ -27,7 +46,7 @@ /(%E5%BF%83%E5%BE%97)%E4%B8%8D%E5%90%88%E9%82%8F%E8%BC%AF%E7%9A%84%E4%B8%80%E5%91%A8/ - 不合邏輯的一周
  • 申請租屋補助不需要房東同意,但如果房東沒有照建物謄本寫合約地址,補件需要房東簽名

  • 隔年會寄稅率變動單給房東,制式租約清楚寫著因稅率變動產生費用由房客承擔

  • 玩 pubg 被莫名其妙的爆炸擊殺,攻擊者顯示為空,伺服器的除錯訊息被印到客戶端,”empty strings table”。

  • 隊友被飢餓者施加負面效果時,我幫忙解除到一半時跑走,變成只能半蹲爬全場,要修復 bug 只能找到同一個隊友重置。

  • 被 C4 飢餓者擊倒後,隊友救我起來,但是負面效果音效沒有解除,整場都是被殭屍抓起來摔的聲音

  • 地圖建模有 bug,住宅區 B 可以在天空趴趴走,而且殭屍抓不到

  • 開發全聯報表發現兩筆資料異常,一家改名稱,另一家倒掉。

  • 有幾家全聯門市庫存是負的

  • 某 Web worker 庫,API 主要兩個方法,start 跟 stop,但是前人傳入完全不相關的 callback ,一行就能解決的功能變成十幾行,而且效率更差。

  • View 完全不切元件,用一大包的參數、嵌套邏輯來判斷,檔案命名與內容幾乎沒有關聯

  • 買飲料時發現喝波霸的吸管變成細的,買飯時 50 號但店員卻拿 49 號的餐給我。

  • 被煙味臭醒,樓下兩層有人手夾著菸伸出窗戶。

  • 椅子整個髒掉,原以為沾到油漆,後發現是舊外套的膠,衛生紙越擦越大片,拿護手霜抹了 2 小時才清乾淨。

  • 隔壁辦公室冷氣壞掉,水像瀑布一樣從天而降,伺服器都濕了,只能搬超大垃圾桶裝水。

  • 大媽理直氣壯的逆向朝我衝來

  • 還是大媽,在平均車速 50、60 的馬路上仰著頭,哼著歌闖紅燈

  • 8:30 找機車位時完全沒有位置

  • 進電梯時被保全拿酒精亂噴,還說等噴完再搭就好

]]>
+ 不合邏輯的一周
  • 申請租屋補助不需要房東同意,但如果房東沒有照建物謄本寫合約地址,補件需要房東簽名

  • 隔年會寄稅率變動單給房東,制式租約清楚寫著因稅率變動產生費用由房客承擔

  • 玩 pubg 被莫名其妙的爆炸擊殺,攻擊者顯示為空,伺服器的除錯訊息被印到客戶端,“empty strings table”。

  • 隊友被飢餓者施加負面效果時,我幫忙解除到一半時跑走,變成只能半蹲爬全場,要修復 bug 只能找到同一個隊友重置。

  • 被 C4 飢餓者擊倒後,隊友救我起來,但是負面效果音效沒有解除,整場都是被殭屍抓起來摔的聲音

  • 地圖建模有 bug,住宅區 B 可以在天空趴趴走,而且殭屍抓不到

  • 開發全聯報表發現兩筆資料異常,一家改名稱,另一家倒掉。

  • 有幾家全聯門市庫存是負的

  • 某 Web worker 庫,API 主要兩個方法,start 跟 stop,但是前人傳入完全不相關的 callback ,一行就能解決的功能變成十幾行,而且效率更差。

  • View 完全不切元件,用一大包的參數、嵌套邏輯來判斷,檔案命名與內容幾乎沒有關聯

  • 買飲料時發現喝波霸的吸管變成細的,買飯時 50 號但店員卻拿 49 號的餐給我。

  • 被煙味臭醒,樓下兩層有人手夾著菸伸出窗戶。

  • 椅子整個髒掉,原以為沾到油漆,後發現是舊外套的膠,衛生紙越擦越大片,拿護手霜抹了 2 小時才清乾淨。

  • 隔壁辦公室冷氣壞掉,水像瀑布一樣從天而降,伺服器都濕了,只能搬超大垃圾桶裝水。

  • 大媽理直氣壯的逆向朝我衝來

  • 還是大媽,在平均車速 50、60 的馬路上仰著頭,哼著歌闖紅燈

  • 8:30 找機車位時完全沒有位置

  • 進電梯時被保全拿酒精亂噴,還說等噴完再搭就好

]]>
@@ -46,7 +65,7 @@ /(%E6%8A%80%E8%A1%93)%E4%BD%BF%E7%94%A8Swagger%E7%94%9F%E6%88%90Laravel%E7%9A%84API%E6%96%87%E4%BB%B6/ - Swagger 可以用來生成 Laravel API 文件,輕鬆地記錄和分享 API 的資訊,提供了清晰的介面,
讓開發人員更容易了解和使用您的 API。這有助於提高開發效率並確保 API 文檔的一致性

安裝

1
composer require "darkaonline/l5-swagger"

Controller

加入文件版本、標題、描述、授權

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
namespace App\Http\Controllers;

use OpenApi\Annotations as OA;
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
use Illuminate\Foundation\Bus\DispatchesJobs;
use Illuminate\Foundation\Validation\ValidatesRequests;
use Illuminate\Routing\Controller as BaseController;

/**
* @OA\Info(
* version="1.0.0",
* title="Book-RESTful-API",
* description="Login to obtain a JWT, with bearer authorization",
* @OA\Contact(
* email="demo@example.com"
* ),
* @OA\License(
* name="Apache 2.0",
* url="http://www.apache.org/licenses/LICENSE-2.0.html"
* )
* )
*/

class Controller extends BaseController
{
use AuthorizesRequests, DispatchesJobs, ValidatesRequests;
}

BookController

新增CRUD註解

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209

namespace App\Http\Controllers;

use App\Models\Book;
use App\Http\Resources\BookResource;
use Illuminate\Http\Request;

class BookController extends Controller
{
/**
* Display a listing of the resource.
*
* @return \Illuminate\Http\Response
*/

public function __construct()
{
$this->middleware('auth:api')->except(['index', 'show']);
}
/**
* @OA\Get(
* path="/api/books",
* summary="取得最多25筆的書本與評分",
* tags={"Book"},
* @OA\Response(response="200", description="成功",@OA\JsonContent()),
* )
*/
public function index()
{
return BookResource::collection(Book::with('ratings')->paginate(25));
}
/**
* @OA\POST(
* path="/api/books",
* summary="創建書本",
* tags={"Book"},
* @OA\RequestBody(
* required=true,
* @OA\MediaType(
* mediaType="application/json",
* @OA\Schema(
* required={"title", "description"},
* @OA\Property(
* property="title",
* type="string",
* description="標題"
* ),
* @OA\Property(
* property="description",
* type="string",
* description="簡介"
* )
* )
* )
* ),
* @OA\Response(
* response=201,
* description="創建成功"
* ),
* @OA\Response(
* response=401,
* description="未驗證"
* ),
* @OA\Response(
* response=404,
* description="資源不存在"
* ),
* security={{ "bearer_token": {} }}
* )
*/

public function store(Request $request)
{
$book = Book::create([
'user_id' => $request->user()->id,
'title' => $request->title,
'description' => $request->description,
]);

return new BookResource($book);
}

/**
* @OA\Get(
* path="/api/books/{bookId}",
* summary="取得書本",
* tags={"Book"},
* @OA\Parameter(
* name="bookId",
* description="Book id",
* required=true,
* in="path",
* @OA\Schema(
* type="integer"
* )
* ),
* @OA\Response(
* response=200,
* description="成功"
* ),
* @OA\Response(
* response=404,
* description="資源不存在"
* )
* )
*/
public function show(Book $book)
{
return new BookResource($book);
}

/**
* @OA\Patch(
* path="/api/books/{bookId}",
* summary="更新書本",
* tags={"Book"},
* description="更新書本",
* @OA\Parameter(
* name="bookId",
* description="Book id",
* required=true,
* in="path",
* @OA\Schema(
* type="integer"
* )
* ),
* @OA\RequestBody(
* description="更新書本的內容",
* required=true,
* @OA\MediaType(
* mediaType="application/json",
* @OA\Schema(
* type="object",
* @OA\Property(
* property="title",
* description="標題",
* type="string"
* ),
* @OA\Property(
* property="description",
* description="內容",
* type="string"
* ),
* )
* )
* ),
* @OA\Response(
* response=200,
* description="成功",
* @OA\JsonContent()
* ),
* @OA\Response(
* response=401,
* description="未驗證",
* @OA\JsonContent()
* ),
* @OA\Response(
* response=404,
* description="資源不存在",
* @OA\JsonContent()
* ),
* security={{ "bearer_token": {} }}
* )
*/
public function update(Request $request, Book $book)
{
if ($request->user()->id !== $book->user_id) {
return response()->json(['error' => 'You can only edit your own books.'], 403);
}

$book->update($request->only(['title', 'description']));

return new BookResource($book);
}

/**
* @OA\Delete(
* path="/api/books/{bookId}",
* summary="刪除書本",
* tags={"Book"},
* @OA\Parameter(
* name="bookId",
* description="Book id",
* required=true,
* in="path",
* @OA\Schema(
* type="integer"
* )
* ),
* @OA\Response(
* response=204,
* description="刪除成功",
* @OA\JsonContent()
* ),
* @OA\Response(
* response=404,
* description="資源不存在",
* @OA\JsonContent()
* ),
* security={{ "bearer_token": {} }}
* )
*/
public function destroy(Book $book)
{
$book->delete();

return response()->json(null, 204);
}
}

生成文件

1
php artisan l5-swagger:generate

訪問以下路由即可看到文件

1
<server>/api/documention

demo

範例在這

Ref

L5-Swagger
swagger-demo
use JWT Bearer token in swagger Laravel

]]>
+ Swagger 可以用來生成 Laravel API 文件,輕鬆地記錄和分享 API 的資訊,提供了清晰的介面,
讓開發人員更容易了解和使用您的 API。這有助於提高開發效率並確保 API 文檔的一致性

安裝

1
composer require "darkaonline/l5-swagger"

Controller

加入文件版本、標題、描述、授權

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
namespace App\Http\Controllers;

use OpenApi\Annotations as OA;
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
use Illuminate\Foundation\Bus\DispatchesJobs;
use Illuminate\Foundation\Validation\ValidatesRequests;
use Illuminate\Routing\Controller as BaseController;

/**
* @OA\Info(
* version="1.0.0",
* title="Book-RESTful-API",
* description="Login to obtain a JWT, with bearer authorization",
* @OA\Contact(
* email="demo@example.com"
* ),
* @OA\License(
* name="Apache 2.0",
* url="http://www.apache.org/licenses/LICENSE-2.0.html"
* )
* )
*/

class Controller extends BaseController
{
use AuthorizesRequests, DispatchesJobs, ValidatesRequests;
}

BookController

新增CRUD註解

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209

namespace App\Http\Controllers;

use App\Models\Book;
use App\Http\Resources\BookResource;
use Illuminate\Http\Request;

class BookController extends Controller
{
/**
* Display a listing of the resource.
*
* @return \Illuminate\Http\Response
*/

public function __construct()
{
$this->middleware('auth:api')->except(['index', 'show']);
}
/**
* @OA\Get(
* path="/api/books",
* summary="取得最多25筆的書本與評分",
* tags={"Book"},
* @OA\Response(response="200", description="成功",@OA\JsonContent()),
* )
*/
public function index()
{
return BookResource::collection(Book::with('ratings')->paginate(25));
}
/**
* @OA\POST(
* path="/api/books",
* summary="創建書本",
* tags={"Book"},
* @OA\RequestBody(
* required=true,
* @OA\MediaType(
* mediaType="application/json",
* @OA\Schema(
* required={"title", "description"},
* @OA\Property(
* property="title",
* type="string",
* description="標題"
* ),
* @OA\Property(
* property="description",
* type="string",
* description="簡介"
* )
* )
* )
* ),
* @OA\Response(
* response=201,
* description="創建成功"
* ),
* @OA\Response(
* response=401,
* description="未驗證"
* ),
* @OA\Response(
* response=404,
* description="資源不存在"
* ),
* security={{ "bearer_token": {} }}
* )
*/

public function store(Request $request)
{
$book = Book::create([
'user_id' => $request->user()->id,
'title' => $request->title,
'description' => $request->description,
]);

return new BookResource($book);
}

/**
* @OA\Get(
* path="/api/books/{bookId}",
* summary="取得書本",
* tags={"Book"},
* @OA\Parameter(
* name="bookId",
* description="Book id",
* required=true,
* in="path",
* @OA\Schema(
* type="integer"
* )
* ),
* @OA\Response(
* response=200,
* description="成功"
* ),
* @OA\Response(
* response=404,
* description="資源不存在"
* )
* )
*/
public function show(Book $book)
{
return new BookResource($book);
}

/**
* @OA\Patch(
* path="/api/books/{bookId}",
* summary="更新書本",
* tags={"Book"},
* description="更新書本",
* @OA\Parameter(
* name="bookId",
* description="Book id",
* required=true,
* in="path",
* @OA\Schema(
* type="integer"
* )
* ),
* @OA\RequestBody(
* description="更新書本的內容",
* required=true,
* @OA\MediaType(
* mediaType="application/json",
* @OA\Schema(
* type="object",
* @OA\Property(
* property="title",
* description="標題",
* type="string"
* ),
* @OA\Property(
* property="description",
* description="內容",
* type="string"
* ),
* )
* )
* ),
* @OA\Response(
* response=200,
* description="成功",
* @OA\JsonContent()
* ),
* @OA\Response(
* response=401,
* description="未驗證",
* @OA\JsonContent()
* ),
* @OA\Response(
* response=404,
* description="資源不存在",
* @OA\JsonContent()
* ),
* security={{ "bearer_token": {} }}
* )
*/
public function update(Request $request, Book $book)
{
if ($request->user()->id !== $book->user_id) {
return response()->json(['error' => 'You can only edit your own books.'], 403);
}

$book->update($request->only(['title', 'description']));

return new BookResource($book);
}

/**
* @OA\Delete(
* path="/api/books/{bookId}",
* summary="刪除書本",
* tags={"Book"},
* @OA\Parameter(
* name="bookId",
* description="Book id",
* required=true,
* in="path",
* @OA\Schema(
* type="integer"
* )
* ),
* @OA\Response(
* response=204,
* description="刪除成功",
* @OA\JsonContent()
* ),
* @OA\Response(
* response=404,
* description="資源不存在",
* @OA\JsonContent()
* ),
* security={{ "bearer_token": {} }}
* )
*/
public function destroy(Book $book)
{
$book->delete();

return response()->json(null, 204);
}
}

生成文件

1
php artisan l5-swagger:generate

訪問以下路由即可看到文件

1
<server>/api/documention

demo

範例在這

Ref

L5-Swagger
swagger-demo
use JWT Bearer token in swagger Laravel

]]>
@@ -65,18 +84,18 @@ /(%E6%8A%80%E8%A1%93)%E5%AF%A6%E4%BD%9CLaravel-RESTful-API%E8%88%87JWT%E9%A9%97%E8%AD%89/ - RESTful API

Representational State Transfer (REST) 是一種軟體架構,它對 API 的運作方式施加了條件。REST 最初是作為管理複雜網路 (如網際網路) 上的通訊指導方針而建立。您可以使用以 REST 為基礎的架構,來支援大規模的高效能和可靠的通訊。您可以輕鬆實作和修改,為任何 API 系統提供可視性和跨平台可移植性。

風格

  • 統一介面
  • 無狀態
  • 分層系統
  • 可快取性
  • 隨需編碼

方法

  • URL
  • GET
  • POST
  • PUT
  • DELETE

幂等

同樣的請求被執行一次與連續執行多次,在伺服器的效果是一樣的,GET、HEAD、PUT、DELETE 是冪等的,POST 方法不是

JWT

JSON Web Token,在伺服器間將訊息作為 JSON 物件傳輸,由 header、payload、signature 組成,
常搭配 RESTful API 作為身分驗證。

實作

安裝

1
composer require tymon/jwt-auth

生成密鑰

1
php artisan jwt:secret

創建 BookResource、BookController

1
php artisan make:resource BookResource
1
php artisan make:controller BookController --api

加入 Middleware

1
2
3
4
public function __construct()
{
$this->middleware('auth:api')->except(['index', 'show']);
}

Postmon 測試

登入取得 access token,預設有效時間一小時

加入 API Header,用來驗證使用者身分

1
Authorization : Bearer <access token>

成功新增資源

demo

範例在這

Ref

什麼是 RESTful API?
冪等
Build a REST API with Laravel API resources

]]>
+ RESTful API

Representational State Transfer (REST) 是一種軟體架構,它對 API 的運作方式施加了條件。REST 最初是作為管理複雜網路 (如網際網路) 上的通訊指導方針而建立。您可以使用以 REST 為基礎的架構,來支援大規模的高效能和可靠的通訊。您可以輕鬆實作和修改,為任何 API 系統提供可視性和跨平台可移植性。

風格

  • 統一介面
  • 無狀態
  • 分層系統
  • 可快取性
  • 隨需編碼

方法

  • URL
  • GET
  • POST
  • PUT
  • DELETE

幂等

同樣的請求被執行一次與連續執行多次,在伺服器的效果是一樣的,GET、HEAD、PUT、DELETE 是冪等的,POST 方法不是

JWT

JSON Web Token,在伺服器間將訊息作為 JSON 物件傳輸,由 header、payload、signature 組成,
常搭配 RESTful API 作為身分驗證。

實作

安裝

1
composer require tymon/jwt-auth

生成密鑰

1
php artisan jwt:secret

創建 BookResource、BookController

1
php artisan make:resource BookResource
1
php artisan make:controller BookController --api

加入 Middleware

1
2
3
4
public function __construct()
{
$this->middleware('auth:api')->except(['index', 'show']);
}

Postmon 測試

登入取得 access token,預設有效時間一小時

加入 API Header,用來驗證使用者身分

1
Authorization : Bearer <access token>

成功新增資源

demo

範例在這

Ref

什麼是 RESTful API?
冪等
Build a REST API with Laravel API resources

]]>
+ Laravel + RESTful API JWT - Laravel -
@@ -88,7 +107,7 @@ /(%E5%BF%83%E5%BE%97)Linda-Rising%E6%95%8F%E6%8D%B7%E6%80%9D%E7%B6%AD%E7%9A%84%E5%8A%9B%E9%87%8F/ - 敏捷 vs 固定

實驗中,敏捷思維的學生更願意接受更難的考試、不確定性高的挑戰,固定思維的學生則傾向於證明自己,選擇簡單的考試,力求完美,總結來說,前者願意不斷接受新的挑戰、機會,讓自己成長,後者傾向滿足於過去的成就,力求穩定,實驗的結尾,具備敏捷思維的學生得益於過去的成長,因此有更佳的表現

固定敏捷
能力靜態動態
目的看起來好學習
挑戰避免接受
失敗命中注定獲得資訊
努力因為沒天分專精
態度無助有彈性

Enron 的固定思維

末位淘汰制下,人們破壞別人的專案,使別人看起來很差,讓自己看起來很好,提升自己的排名
,降低被淘汰的風險,但這樣有毒的政策,使公司很快倒閉

西南航空的敏捷思維

西南態度,讓公司成長、學習、變得更好,也鼓勵員工有實驗精神

總結

生而敏捷,不斷地跌倒犯錯成長,成長環境不同,有人在一聲聲稱讚中迷失自我,變得保守,有人在過程中獲得成長,變得敏捷,不斷進步,筆者身邊的小鎮做題家,求學時期即非常優秀,成績名列前茅,擅長社交,通常原生家庭對他們有極高的要求,但人無完人,再優秀也會碰到難關,課業、感情、社交,但自尊心使他們不願意向外界求助,很遺憾地,有人就這樣被困在歷史的夾縫,努力保持過去的榮耀,卻駐足不前,敏捷思維能夠解決這樣的困境,卻不是每個人都可以接受。

]]>
+ 敏捷 vs 固定

實驗中,敏捷思維的學生更願意接受更難的考試、不確定性高的挑戰,固定思維的學生則傾向於證明自己,選擇簡單的考試,力求完美,總結來說,前者願意不斷接受新的挑戰、機會,讓自己成長,後者傾向滿足於過去的成就,力求穩定,實驗的結尾,具備敏捷思維的學生得益於過去的成長,因此有更佳的表現

固定敏捷
能力靜態動態
目的看起來好學習
挑戰避免接受
失敗命中注定獲得資訊
努力因為沒天分專精
態度無助有彈性

Enron 的固定思維

末位淘汰制下,人們破壞別人的專案,使別人看起來很差,讓自己看起來很好,提升自己的排名
,降低被淘汰的風險,但這樣有毒的政策,使公司很快倒閉

西南航空的敏捷思維

西南態度,讓公司成長、學習、變得更好,也鼓勵員工有實驗精神

總結

生而敏捷,不斷地跌倒犯錯成長,成長環境不同,有人在一聲聲稱讚中迷失自我,變得保守,有人在過程中獲得成長,變得敏捷,不斷進步,筆者身邊的小鎮做題家,求學時期即非常優秀,成績名列前茅,擅長社交,通常原生家庭對他們有極高的要求,但人無完人,再優秀也會碰到難關,課業、感情、社交,但自尊心使他們不願意向外界求助,很遺憾地,有人就這樣被困在歷史的夾縫,努力保持過去的榮耀,卻駐足不前,敏捷思維能夠解決這樣的困境,卻不是每個人都可以接受。

]]>
@@ -107,7 +126,7 @@ /(%E6%8A%80%E8%A1%93)%E9%80%8F%E9%81%8EGithub-Action%E5%AF%A6%E7%8F%BECICD-Pipeline/ -

How to use

  • git clone

    1
    https://github.com/chienniman/mantine-vite-template.git
  • download the ZIP

  • fork the project

Create a new repository

Selected Public to host free gh-page app

Create CI/CD workflow

.github /workflows/main.yml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
name: Deploy to gh-page
permissions:
contents: write
on:
push:
branches: master

jobs:
build:
name: Build
runs-on: ubuntu-latest

steps:
- name: Checkout repo
uses: actions/checkout@v3

- name: Setup Node
uses: actions/setup-node@v2

- name: CI
run: npm ci

- name: Typecheck
run: npm run typecheck

- name: Prettier
run: npm run prettier

- name: Lint
run: npm run lint

- name: Jest
run: npm run jest

- name: Run build
run: npm run build

- name: Upload production-ready build files
uses: actions/upload-artifact@v2
with:
name: production-files
path: ./dist

deploy:
name: Deploy
needs: build
runs-on: ubuntu-latest
if: github.ref == 'refs/heads/master'

steps:
- name: Download artifact
uses: actions/download-artifact@v2
with:
name: production-files
path: ./dist

- name: Deploy to gh-pages
uses: peaceiris/actions-gh-pages@v3
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
publish_dir: ./dist

Local development and usage

install yarn

1
yarn --version
1
npm install --global yarn

install node_modules

1
yarn install

add homepage to package.json

1
"homepage": "https://<githubusername>.github.io/<app>"

Start the vite server and develop new features.

1
npm run dev

test

1
npm run test

Commit to master branch

1
2
3
git init
git add .
git commit -m "xxx"

Enable GitHub Pages

The source must be set to gh-pages instead of master/main, otherwise it will not be displayed.

Done

Discussion

To fix the issue of resource loading 404 errors and modify the default path, you can achieve it through the configuration in vite.config.ts.

vite.config.ts

1
2
3
4
5
6
7
8
9
10
11
12
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';

// https://vitejs.dev/config/
export default defineConfig({
plugins: [react()],
base: '/mantine-vite-template/',
build: {
assetsDir: 'assets',
},
});

Pages build and deployment

I think there’s a lot of scope for confusion for users of this action, when pages build and deployment will also be running on every push and pushing pages assets.

I think it’s impossible to really say right now what that looks like until GitHub announces what these actions intend to do in the long run. As the post suggests this is a necessary step that occurs after the push gets made, this was already occurring behind the scenes it just wasn’t made visible.

Ref

yarn
What is actions/checkout@v2 in Github action
deploy-to-github-pages
vite-deploy-demo
antonputra/tutorials
github-pages-deploy-action

]]>
+

How to use

  • git clone
1
https://github.com/chienniman/mantine-vite-template.git
  • download the ZIP

  • fork the project

Create a new repository

Selected Public to host free gh-page app

Create CI/CD workflow

.github /workflows/main.yml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
name: Deploy to gh-page
permissions:
contents: write
on:
push:
branches: master

jobs:
build:
name: Build
runs-on: ubuntu-latest

steps:
- name: Checkout repo
uses: actions/checkout@v3

- name: Setup Node
uses: actions/setup-node@v2

- name: CI
run: npm ci

- name: Typecheck
run: npm run typecheck

- name: Prettier
run: npm run prettier

- name: Lint
run: npm run lint

- name: Jest
run: npm run jest

- name: Run build
run: npm run build

- name: Upload production-ready build files
uses: actions/upload-artifact@v2
with:
name: production-files
path: ./dist

deploy:
name: Deploy
needs: build
runs-on: ubuntu-latest
if: github.ref == 'refs/heads/master'

steps:
- name: Download artifact
uses: actions/download-artifact@v2
with:
name: production-files
path: ./dist

- name: Deploy to gh-pages
uses: peaceiris/actions-gh-pages@v3
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
publish_dir: ./dist

Local development and usage

install yarn

1
yarn --version
1
npm install --global yarn

install node_modules

1
yarn install

add homepage to package.json

1
"homepage": "https://<githubusername>.github.io/<app>"

Start the vite server and develop new features.

1
npm run dev

test

1
npm run test

Commit to master branch

1
2
3
git init
git add .
git commit -m "xxx"

Enable GitHub Pages

The source must be set to gh-pages instead of master/main, otherwise it will not be displayed.

Done

Discussion

To fix the issue of resource loading 404 errors and modify the default path, you can achieve it through the configuration in vite.config.ts.

vite.config.ts

1
2
3
4
5
6
7
8
9
10
11
12
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';

// https://vitejs.dev/config/
export default defineConfig({
plugins: [react()],
base: '/mantine-vite-template/',
build: {
assetsDir: 'assets',
},
});

Pages build and deployment

I think there’s a lot of scope for confusion for users of this action, when pages build and deployment will also be running on every push and pushing pages assets.

I think it’s impossible to really say right now what that looks like until GitHub announces what these actions intend to do in the long run. As the post suggests this is a necessary step that occurs after the push gets made, this was already occurring behind the scenes it just wasn’t made visible.

Ref

yarn
What is actions/checkout@v2 in Github action
deploy-to-github-pages
vite-deploy-demo
antonputra/tutorials
github-pages-deploy-action

]]>
@@ -136,7 +155,7 @@ /(%E9%81%8A%E6%88%B2)%E4%B8%8D%E9%9D%A0T%E8%BD%89%E8%B7%9F%E5%AE%8C%E7%BE%8E%E6%B6%88%E9%99%A4%E9%81%94%E5%88%B0TETR%E7%9A%84S%E7%89%8C%E4%BD%8D/ -

2022 年因為伺服器延遲問題從特戰英豪退坑後,每周零零散散的玩幾場 CSGO 競技,不得不說在基建的部分,V 社做得比拳頭好很多,像特戰英豪這種高強度競技射擊,PING 飆到 200、300 基本上走出去就被爆頭了(白金~鑽石),無遊戲體驗可言,心灰意冷轉戰 2021 年時發現的俄羅斯方塊,沒有搞氣氛的隊友,沒有馬鈴薯伺服器,勝負大機率取決於個人技巧。

介紹兩個特殊技巧,T 轉(T-Spin)完美消除(Perfect Clear)

完美消除(Perfect Clear)

透過特殊擺法消除場上所有方塊,不包含垃圾

開場造成 10 行以上的攻擊(取決於 B2B combo),非常致命

T-Spin

顧名思義,透過旋轉 T 方塊的特殊消行技巧,每個遊戲有不同計算方式,以下是 4 個 T-spin Triple 加上一個 mini single 的示範

牌位

D~C+

先贏 3 場,入門級,速度緩慢,失誤多,方塊擺放不整齊就開始消行,注重自身的防守。

B-~B+

先贏 3 場,頻繁使用連招,小失誤,比拚消行速度與時機點把握,推薦空 2、3 行,重點在懲罰對手的失誤。

A-~A+

先贏 3 場,實力落差大,不穩定的玩家在 B+~A-震盪,穩定型會在 A+卡一陣子,專注於B2B Combo,雙方基本不失誤,差別於爆發總量,受到手感跟方塊擺放邏輯影響,不能有明顯弱點,方塊高低起伏過大、速度偏慢、COMBO 少、小失誤,容易被一波帶走。

S-~SS

先贏 5場,T 轉跟完美消除是基本盤,手感、運氣下滑或 B2B Combo 中斷,被打亂節奏,高處被卡死是家常便飯。

爆發型

開局連續 T 轉、完美消除使對手來不及疊高 Combo 就被 KO

優點

  • 前期優勢
  • 方塊高度低

缺點

  • 手感、運氣差容易被懲罰
  • 過度依賴於特定方塊
  • 容錯率低

穩定型

持續疊高,留 1~3 空行

優點

  • 一行能保持 B2B Combo,二到三行能在後期大量轟炸
  • 容錯高,堆疊快
  • 可攻可守

缺點

  • 爆發總行少
  • 開局劣勢

S 級有不少手速快到令人咋舌的玩家,但還是能透過合理分析,選用策略來增加勝率,在開場時觀察,如果發現對手擺放固定套路,準備完美消除或是連續 T 轉,進行Quad(4 消行)循環,保持 B2B Combo(不參雜單、雙、三消行),能帶來額外的攻擊行數,對T轉苦手很有幫助。
對手將方塊疊高,留 1~3 行,短時間大量轟炸,如果自身手感下滑,建議將地基打掉扛住這波爆發,順著對手的步調走硬碰硬,因為對手的輸出總量等於自身累積+消除垃圾行,沒有足夠的行數抵銷,容易陷入劣勢。

總結

Tetr 鼓勵使用不中斷的 T 轉或是 Quad,不崇尚單消行防守,這點可以從B2B Combo累計表看出,曾經風靡一時的臉書遊戲Tetris Battle,會在KO數相同時比較總消行數,但Tetr只考慮誰先取得足夠勝場,前期消行慢,仔細思考布置也是一種遊戲風格,帶來更大的自由性,不會因前期劣勢滾雪球,導致不可挽回的敗北。

]]>
+

2022 年因為伺服器延遲問題從特戰英豪退坑後,每周零零散散的玩幾場 CSGO 競技,不得不說在基建的部分,V 社做得比拳頭好很多,像特戰英豪這種高強度競技射擊,PING 飆到 200、300 基本上走出去就被爆頭了(白金~鑽石),無遊戲體驗可言,心灰意冷轉戰 2021 年時發現的俄羅斯方塊,沒有搞氣氛的隊友,沒有馬鈴薯伺服器,勝負大機率取決於個人技巧。

介紹兩個特殊技巧,T 轉(T-Spin)完美消除(Perfect Clear)

完美消除(Perfect Clear)

透過特殊擺法消除場上所有方塊,不包含垃圾

開場造成 10 行以上的攻擊(取決於 B2B combo),非常致命

T-Spin

顧名思義,透過旋轉 T 方塊的特殊消行技巧,每個遊戲有不同計算方式,以下是 4 個 T-spin Triple 加上一個 mini single 的示範

牌位

D~C+

先贏 3 場,入門級,速度緩慢,失誤多,方塊擺放不整齊就開始消行,注重自身的防守。

B-~B+

先贏 3 場,頻繁使用連招,小失誤,比拚消行速度與時機點把握,推薦空 2、3 行,重點在懲罰對手的失誤。

A-~A+

先贏 3 場,實力落差大,不穩定的玩家在 B+~A-震盪,穩定型會在 A+卡一陣子,專注於B2B Combo,雙方基本不失誤,差別於爆發總量,受到手感跟方塊擺放邏輯影響,不能有明顯弱點,方塊高低起伏過大、速度偏慢、COMBO 少、小失誤,容易被一波帶走。

S-~SS

先贏 5場,T 轉跟完美消除是基本盤,手感、運氣下滑或 B2B Combo 中斷,被打亂節奏,高處被卡死是家常便飯。

爆發型

開局連續 T 轉、完美消除使對手來不及疊高 Combo 就被 KO

優點

  • 前期優勢
  • 方塊高度低

缺點

  • 手感、運氣差容易被懲罰
  • 過度依賴於特定方塊
  • 容錯率低

穩定型

持續疊高,留 1~3 空行

優點

  • 一行能保持 B2B Combo,二到三行能在後期大量轟炸
  • 容錯高,堆疊快
  • 可攻可守

缺點

  • 爆發總行少
  • 開局劣勢

S 級有不少手速快到令人咋舌的玩家,但還是能透過合理分析,選用策略來增加勝率,在開場時觀察,如果發現對手擺放固定套路,準備完美消除或是連續 T 轉,進行Quad(4 消行)循環,保持 B2B Combo(不參雜單、雙、三消行),能帶來額外的攻擊行數,對T轉苦手很有幫助。
對手將方塊疊高,留 1~3 行,短時間大量轟炸,如果自身手感下滑,建議將地基打掉扛住這波爆發,順著對手的步調走硬碰硬,因為對手的輸出總量等於自身累積+消除垃圾行,沒有足夠的行數抵銷,容易陷入劣勢。

總結

Tetr 鼓勵使用不中斷的 T 轉或是 Quad,不崇尚單消行防守,這點可以從B2B Combo累計表看出,曾經風靡一時的臉書遊戲Tetris Battle,會在KO數相同時比較總消行數,但Tetr只考慮誰先取得足夠勝場,前期消行慢,仔細思考布置也是一種遊戲風格,帶來更大的自由性,不會因前期劣勢滾雪球,導致不可挽回的敗北。

]]>
@@ -155,7 +174,7 @@ /(%E5%BF%83%E5%BE%97)%E4%B8%8D%E5%B9%B8%E8%B2%B7%E5%88%B0%E4%B8%83%E9%80%B2%E4%B8%83%E5%87%BA%E5%AD%90%E9%BE%8D%E6%A9%9F%E6%98%AF%E4%BB%80%E9%BA%BC%E9%AB%94%E9%A9%97/ -

在台灣購買桌電有很多管道,但建議盡量到實體通路,購買有保障、評價好的品牌機,價格稍高,但可以省下大把時間,
不需搬著幾公斤的鐵塊到處解被動觸發的子龍任務。

這台電腦在 2020 年初購入,當時的想法很簡單,上課報告寫作業,i5 的舊筆電綽綽有餘,當時對買電腦完全沒概念,只知道 CPU 好就夠了(這不全然正確,想想看在小金龜上裝法拉利的引擎),興致勃勃地上網,在某網購平台看到,電競水冷機 RTX-2060+i7-9700K,竟然只要 3 萬出頭,不管三七二十一就火速下單,送到家剛開機時,七彩奪目的 RGB 燈,半透明側板,未來龐克設計的水冷系統,讓我興奮地整晚睡不著覺。

當時沉浸在刺客教條帶給我的 3A 絕佳體驗,毫無意識到 40%爆擊的背刺正攻向我,那是一個美好的清晨,奇怪,開機怎麼發出 bbb 蜂鳴器的刺耳叫聲,卡在 bios,其實是UEFI,而且讀不到硬碟?花了幾天瞎搞當然是無疾而終,沒備用零件、沒電壓表,如何交叉測試,花了 400 多塊請了個年紀跟我差不多的大學生幫我看,但他拿著無線鍵盤鼓搗了 3 小時只得出可能是主機板的問題的結論,廢話,那我花錢請你來幹嘛,無奈,車馬費還是得付。

撥通原廠電話(不是平台,是負責出貨的廠商),對方態度並不是很好,一副跟他無關的樣子,當時也只能憋著一肚子氣,畢竟這台新機才剛到貨 2 個月,過了一個禮拜接到對方公司的電話,理由十分荒謬,bios 設定有問題,那邊測都沒有問題,得到這樣的答覆我並不意外,畢竟如果承認並被客人錄音,可能會導致公司的商譽損失,但不斷推卸責任並且拒絕認錯的態度真的讓人觀感非常差。

摸摸鼻子就認了,能用這種價格享受”電競級”桌電,已經很划算,當年底,再次壞去,這次是不斷開機、斷電的無限輪迴,黑貓物流很快就載回去原廠,猜猜這次給的理由是甚麼? “完全沒有問題!這邊測都可以正常開機”,氣到直接笑出來,反問要不要把秀斗的影片傳給他看,毫不意外的客服持續跳針,像留聲機一樣,重複應著荒謬又諷刺的”官方說法”。

到這裡已經對這家公司不抱任何期待,先不說他們修完電腦還忘記幫我安裝作業系統,又噴了一筆微軟授權費,就這樣風平浪靜地度過了一年,還記得那是個炎熱的下午,此起彼落的蜂鳴聲呼應著窗外的蟬鳴,又來,有完沒完,也知道結局跟理由是甚麼了,唯一不同的是被另外收了 1000 元的”檢測費”,到目前為止維修這台電腦的成本已經可以購買上一個檔次的電腦了,只希望不要再出問題。
玩遊戲到一半畫面卡住,上網查可能是記憶體接觸不良,自己隨便弄重裝好了就不理了,繼續用,昨天,跑程式有點卡頓,記憶體只剩一條在運作,Windows 大量的背景程式讓 Ram 飆到 80、90%,拆開主機滿滿的灰塵彷彿濃霧散出,決定花錢消災,請人幫我清潔、上油,又能動了。

低於市場行情的 3C 設備真的要慎選,平板、電腦、手機有所謂福利品,電腦零件同樣也有,價格甚至不到正常品的一半,惡劣一點的拿伺服器拆下來的垃圾重組,外行人也看不出來,整包算下來真的不划算,羊毛出在羊身上,價格便宜是犧牲品質、使用者體驗、賣家商譽換出來的,題外話,就算大品牌的筆電故障率不見得比較低,例如台灣的 A 開頭品牌,滔滔不絕的皇家子龍任務災情慘重,奇怪,美國 A 開頭有水果在上面的故障率就很低。

]]>
+

在台灣購買桌電有很多管道,但建議盡量到實體通路,購買有保障、評價好的品牌機,價格稍高,但可以省下大把時間,
不需搬著幾公斤的鐵塊到處解被動觸發的子龍任務。

這台電腦在 2020 年初購入,當時的想法很簡單,上課報告寫作業,i5 的舊筆電綽綽有餘,當時對買電腦完全沒概念,只知道 CPU 好就夠了(這不全然正確,想想看在小金龜上裝法拉利的引擎),興致勃勃地上網,在某網購平台看到,電競水冷機 RTX-2060+i7-9700K,竟然只要 3 萬出頭,不管三七二十一就火速下單,送到家剛開機時,七彩奪目的 RGB 燈,半透明側板,未來龐克設計的水冷系統,讓我興奮地整晚睡不著覺。

當時沉浸在刺客教條帶給我的 3A 絕佳體驗,毫無意識到 40%爆擊的背刺正攻向我,那是一個美好的清晨,奇怪,開機怎麼發出 bbb 蜂鳴器的刺耳叫聲,卡在 bios,其實是UEFI,而且讀不到硬碟?花了幾天瞎搞當然是無疾而終,沒備用零件、沒電壓表,如何交叉測試,花了 400 多塊請了個年紀跟我差不多的大學生幫我看,但他拿著無線鍵盤鼓搗了 3 小時只得出可能是主機板的問題的結論,廢話,那我花錢請你來幹嘛,無奈,車馬費還是得付。

撥通原廠電話(不是平台,是負責出貨的廠商),對方態度並不是很好,一副跟他無關的樣子,當時也只能憋著一肚子氣,畢竟這台新機才剛到貨 2 個月,過了一個禮拜接到對方公司的電話,理由十分荒謬,bios 設定有問題,那邊測都沒有問題,得到這樣的答覆我並不意外,畢竟如果承認並被客人錄音,可能會導致公司的商譽損失,但不斷推卸責任並且拒絕認錯的態度真的讓人觀感非常差。

摸摸鼻子就認了,能用這種價格享受"電競級"桌電,已經很划算,當年底,再次壞去,這次是不斷開機、斷電的無限輪迴,黑貓物流很快就載回去原廠,猜猜這次給的理由是甚麼? “完全沒有問題!這邊測都可以正常開機”,氣到直接笑出來,反問要不要把秀斗的影片傳給他看,毫不意外的客服持續跳針,像留聲機一樣,重複應著荒謬又諷刺的"官方說法"。

到這裡已經對這家公司不抱任何期待,先不說他們修完電腦還忘記幫我安裝作業系統,又噴了一筆微軟授權費,就這樣風平浪靜地度過了一年,還記得那是個炎熱的下午,此起彼落的蜂鳴聲呼應著窗外的蟬鳴,又來,有完沒完,也知道結局跟理由是甚麼了,唯一不同的是被另外收了 1000 元的"檢測費",到目前為止維修這台電腦的成本已經可以購買上一個檔次的電腦了,只希望不要再出問題。
玩遊戲到一半畫面卡住,上網查可能是記憶體接觸不良,自己隨便弄重裝好了就不理了,繼續用,昨天,跑程式有點卡頓,記憶體只剩一條在運作,Windows 大量的背景程式讓 Ram 飆到 80、90%,拆開主機滿滿的灰塵彷彿濃霧散出,決定花錢消災,請人幫我清潔、上油,又能動了。

低於市場行情的 3C 設備真的要慎選,平板、電腦、手機有所謂福利品,電腦零件同樣也有,價格甚至不到正常品的一半,惡劣一點的拿伺服器拆下來的垃圾重組,外行人也看不出來,整包算下來真的不划算,羊毛出在羊身上,價格便宜是犧牲品質、使用者體驗、賣家商譽換出來的,題外話,就算大品牌的筆電故障率不見得比較低,例如台灣的 A 開頭品牌,滔滔不絕的皇家子龍任務災情慘重,奇怪,美國 A 開頭有水果在上面的故障率就很低。

]]>
@@ -174,7 +193,7 @@ /(%E5%BF%83%E5%BE%97)%E6%88%91%E7%9A%84%E7%AC%AC%E4%B8%80%E5%8F%B0Lubuntu%E7%AD%86%E9%9B%BB/ - 前言

以前就想要安裝Linux作業系統,長期習慣Windows介面的我遲未行動,一部分是因為許多Steam遊戲不支援,
舊筆電(使用5年)出現花屏,可能是顯示卡、螢幕問題,拿去修理效益比實在不大,但又有外出攜帶需求,結合價格、使用
頻率、開發需求、硬體規格等多方要素,2021年購入這台不到一萬的迷你筆電。

規格

  • 處理器:IntelR Celeron N4020 Processor 1.1 GHz (4M Cache, up to 2.8 GHz)
  • 記憶體(內建/最大):4GB DDR4
  • 硬碟:64G EMMC

大小跟平板差不多(11.6”HD霧面寬螢幕),重量1.05KG,適合外出,預設安裝Windows10 S模式(只允許 Microsoft Store 上提供的應用程式),整體來說開機相當快速,能上網、文書處理、前後端開發、跑資料庫,不過有時會黑屏閃退,這台小筆電開太多Chrome分頁,CPU就會飆到80、90%,所以桌機就漸漸取代它,直到最近整理時,打算安裝輕量級的Ubuntu版本,使其起死回生。

Lubuntu

Linux有許多版本,適合桌面使用的Ubuntu,常用於伺服器和商業環境,許多其他Linux上游的Debian,CentOS等。
Ubuntu又有許多分支,UbuntuKylin、Kubuntu、Xubuntu、Edubuntu、Mythbuntu,本機選用的Lubuntu輕量、快速,適合老舊機型、規格低下的筆電。

映像檔

先到官方網站下載映像檔,

燒錄開機碟


使用rufus製作開機碟
1.裝置,選擇外接硬碟(USB)
2.開機模式,選擇剛剛下載的Lubuntu映像檔
3.資料分割方式,依照UEFI、BIOS選擇

UEFI(統一可擴充韌體接口)開機

Asus筆電開機時長按F2,進入UEFI,開機順序更改為USB開機

啟動安裝

grub 啟動畫面。
1.安裝,選擇Try 或 Install Lubuntu。
2.顯卡問題,比如較新的 nvidia 卡,選擇safe graphics。
3.測試ram,選擇Test memory。

實時預覽

啟動後,探索 Lubuntu 並確保所有硬體都能正常工作。準備好後,雙擊桌面左上角的圖標

設定

位置

鍵盤

切割硬碟


刪除磁盤。格式化磁盤,請備份所有重要資料。

密碼配置

最後配置檢查

重新啟動,大功告成

參考資料&圖片

lubuntu手冊

]]>
+ 前言

以前就想要安裝Linux作業系統,長期習慣Windows介面的我遲未行動,一部分是因為許多Steam遊戲不支援,
舊筆電(使用5年)出現花屏,可能是顯示卡、螢幕問題,拿去修理效益比實在不大,但又有外出攜帶需求,結合價格、使用
頻率、開發需求、硬體規格等多方要素,2021年購入這台不到一萬的迷你筆電。

規格

  • 處理器:IntelR Celeron N4020 Processor 1.1 GHz (4M Cache, up to 2.8 GHz)
  • 記憶體(內建/最大):4GB DDR4
  • 硬碟:64G EMMC

大小跟平板差不多(11.6"HD霧面寬螢幕),重量1.05KG,適合外出,預設安裝Windows10 S模式(只允許 Microsoft Store 上提供的應用程式),整體來說開機相當快速,能上網、文書處理、前後端開發、跑資料庫,不過有時會黑屏閃退,這台小筆電開太多Chrome分頁,CPU就會飆到80、90%,所以桌機就漸漸取代它,直到最近整理時,打算安裝輕量級的Ubuntu版本,使其起死回生。

Lubuntu

Linux有許多版本,適合桌面使用的Ubuntu,常用於伺服器和商業環境,許多其他Linux上游的Debian,CentOS等。
Ubuntu又有許多分支,UbuntuKylin、Kubuntu、Xubuntu、Edubuntu、Mythbuntu,本機選用的Lubuntu輕量、快速,適合老舊機型、規格低下的筆電。

映像檔

先到官方網站下載映像檔,

燒錄開機碟


使用rufus製作開機碟
1.裝置,選擇外接硬碟(USB)
2.開機模式,選擇剛剛下載的Lubuntu映像檔
3.資料分割方式,依照UEFI、BIOS選擇

UEFI(統一可擴充韌體接口)開機

Asus筆電開機時長按F2,進入UEFI,開機順序更改為USB開機

啟動安裝

grub 啟動畫面。
1.安裝,選擇Try 或 Install Lubuntu。
2.顯卡問題,比如較新的 nvidia 卡,選擇safe graphics。
3.測試ram,選擇Test memory。

實時預覽

啟動後,探索 Lubuntu 並確保所有硬體都能正常工作。準備好後,雙擊桌面左上角的圖標

設定

位置

鍵盤

切割硬碟


刪除磁盤。格式化磁盤,請備份所有重要資料。

密碼配置

最後配置檢查

重新啟動,大功告成

參考資料&圖片

lubuntu手冊

]]>
@@ -201,7 +220,7 @@ /(%E6%8A%80%E8%A1%93)%E5%A4%A7%E5%9E%8B%E9%97%9C%E4%BF%82%E7%AE%A1%E7%90%86Monica/ - Monica 是一個開源專案,用於組織和記錄與親人的互動。又稱 PRM,個人關係管理。可將其視為您朋友或家人的 CRM,本文會介紹感興趣的功能,API、數據導出、OAuth、以及 issue。

Monica’s vision is to help people have more meaningful relationships.
幫助人們建立有意義的關係

主打”關係管理”,相較市面成熟的社交產品(如 Facebook),其定位特別,替人脈建立一個管理後台,還記得大學時參加幹訓、社團迎新,認識各社團幹部,常忘記小細節,此產品便能很好地解決這個問題,基於興趣,我也作為翻譯貢獻者,協助 monica 文件繁體中文的在地化,具體參考chienniman/monica
本文會介紹API授權(個人使用、開放授權),數據導出、社群討論issue,也會同時附上以上功能的原始碼分析,深入淺出的介紹設計模式在本專案的應用。

執行&部署

1
2
3
4
PHP 8.1+
HTTP server with PHP support (eg: Apache, Nginx, Caddy)
Composer
MySQL
1
2
Platform.sh
Heroku

官方文件提到,構建專案程式需要 1.5GB RAM 以上,在 GCP 開便宜的 n1-standard-1,每月最少也要 600 台幣

Authentication

在 Monica 中,OAuth 2.0 與個人訪問令牌是兩種不同的身份驗證機制,但它們都用於授權 API 訪問。
OAuth 2.0 是一種標準的開放授權協議,允許用戶在 Monica 上授權第三方應用程序訪問數據,不需要將用戶名和密碼提供給該應用程序。當用戶通過 OAuth 2.0 授權授權應用程序時,該應用程序會收到一個訪問令牌,以便它可以代表用戶訪問 Monica API。
個人訪問令牌則是一種基於 Monica 賬戶的令牌,允許應用程序代表用戶訪問 Monica API。這意味著,當用戶提供他們的個人訪問令牌給應用程序時,該應用程序就可以代表該用戶訪問 API,就像它擁有 OAuth 2.0 訪問令牌一樣。
雖然這兩種令牌都可以用於授權 API 訪問,但它們的使用方式略有不同。 OAuth 2.0 是一種標準的開放授權協議,允許用戶授權第三方應用程序訪問其數據。個人訪問令牌則是一種在 Monica 內部生成的令牌,只能由用戶本人使用。在大多數情況下,建議使用 OAuth 2.0,因為它是更安全和更靈活的身份驗證協議。

個人驗證授權

1
curl -H "Authorization: Bearer Personal access token" https://app.monicahq.com/api

個人驗證令牌(personal-access-token)


將 token 放在 postmon 的 Authorization

postman測試

開放授權(OAuth)

monica 也提供 OAuth 方式驗證 API,向伺服器發起驗證請求,跳出授權允許視窗,取得 Access Token,之後請求夾帶令牌訪問保護資源

流程

Postmon


配置 postmon 參數,將 Callback URL 填入 monica 後台 API,Token name、Client ID、Client Secret 填入 postmon

授權請求


postmon 會跳出授權請求,允許後核發 Access Token、Refresh Token,點擊使用後自動帶入 Authorization Token 欄位

測試請求


The OAuth 2.0 Authorization Framework: Bearer Token Usage
monica-api 文件

第三方登入

官方託管 monica 支持 OAuth API,卻不支持 Facebook、Google 第三方登入,主流的平台為提升用戶體驗,通常會支持,疑惑地查找社群討論發現

degan6 提出 OAuth 登入的 pull request,但被主要開發者拒絕了

1.不想要支持有疑慮的第三方登入(Facebook 疑似洩漏個資事件)
2.官方託管已經移除大多數的追蹤程式碼

數據導出

monica 能輸出聯絡人vCard,使用者Sql、Json 等,相當便利,數據輸出需較長時間處理,隊列任務被存儲在數據庫,在多個請求之間共享任務。當任務被添加到隊列,被插入到表中,等待被執行。Laravel會跟蹤任務的狀態,未處理、處理中、已處理、失敗。
Laravel預設使用同步隊列(sync),保證實時、穩定性,方便進行開發與測試,但對於大量、耗時任務,同步處理會阻塞主線程,因此不適合高併發場景。

vCard


vCard 是電子名片的文件格式標準。它一般附加在電子郵件之後,但也可以用於其它場合(如在網際網路上相互交換)。vCard 可包含的信息有:姓名、地址資訊、電話號碼、URL,logo,相片等。

Routes

1
2
// monica/routes/web.php 
Route::get('/people/{contact}/vcard', 'ContactsController@vcard')->name('vcard');

ContactsController

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// monica/app/Http/Controllers/ContactsController.php
// 依賴注入:Contact、ExportVCard、Str和LocaleHelper通過依賴注入。
public function vCard(Contact $contact)
{
// 禁用 Debugbar 避免在下載 vCard 時,偵錯列(debugbar)出現在輸出中
if (config('app.debug') && class_exists('\Barryvdh\Debugbar\Facade')) {
Debugbar::disable();
}
// Laravel 中的全域輔助函數,用於從應用程式服務容器中取回特定的服務實例
$vcard = app(ExportVCard::class)->execute([
'account_id' => auth()->user()->account_id,
'contact_id' => $contact->id,
]);
// response 函數將 $vcard 序列化後的 VCard 字符串作為內容,設置 'Content-type' 標頭為 'text/x-vcard'
// 表示傳輸的內容是 VCard 格式。同時,設置 'Content-Disposition' 標頭為 'attachment;
// filename='.Str::slug($contact->name, '-', LocaleHelper::getLang()).'.vcf'
// 表示將其作為下載文件附件發送給用戶端,並將文件名設置為聯絡人的名稱轉換為 slug 格式後加上 .vcf 的檔名
return response($vcard->serialize())
->header('Content-type', 'text/x-vcard')
->header('Content-Disposition', 'attachment; filename='.Str::slug($contact->name, '-', LocaleHelper::getLang()).'.vcf');
}

Sql & Json導出

Routes

1
2
3
// monica/routes/web.php 
Route::post('/settings/exportToSql', 'Settings\\ExportController@storeSQL')->name('export.store.sql');
Route::post('/settings/exportToJson', 'Settings\\ExportController@storeJson')->name('export.store.json');

ExportJob

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
// monica/app/Models/Account/ExportJob.php 
namespace App\Models\Account;

use App\Traits\HasUuid;
use App\Models\User\User;
use Illuminate\Database\Eloquent\Model;
use App\Notifications\ExportAccountDone;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Factories\HasFactory;

class ExportJob extends Model
{
use HasUuid, HasFactory;

public const EXPORT_TODO = 'todo';
public const EXPORT_DOING = 'doing';
public const EXPORT_DONE = 'done';
public const EXPORT_FAILED = 'failed';

public const SQL = 'sql';

public const JSON = 'json';

protected $fillable = [
'uuid',
'account_id',
'user_id',
'type',
'status',
'filesystem',
'filename',
'started_at',
'ended_at',
];

protected $guarded = ['id'];

protected $dates = [
'started_at',
'ended_at',
];

public function account()
{
return $this->belongsTo(Account::class);
}

public function user()
{
return $this->belongsTo(User::class);
}

public function start(): void
{
$this->status = self::EXPORT_DOING;
$this->started_at = now();
$this->save();
}

// 發信通知
public function end(): void
{
$this->status = self::EXPORT_DONE;
$this->ended_at = now();
$this->save();

$this->user->notify(new ExportAccountDone($this));
}
}

ExportController

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
// monica/app/Http/Controllers/Settings/ExportController.php
private function newExport(string $type): ExportJob
{
$exports = ExportJob::where([
'account_id' => auth()->user()->account_id,
'user_id' => auth()->user()->id,
])
->orderBy('created_at')
->get();
// 輸出任務總量超過最大配置,刪除最舊的任務
if ($exports->count() >= config('monica.export_size')) {
$job = $exports->first();
try {
if ($job->filename !== null) {
StorageHelper::disk($job->location)
->delete($job->filename);
}
} finally {
// 確保釋放資源,避免內存洩漏、資源浪費
$job->delete();
}
}
// 回傳剛建立的實例資料
return ExportJob::create([
'account_id' => auth()->user()->account_id,
'user_id' => auth()->user()->id,
'type' => $type,
]);
}

public function storeSql()
{
$job = $this->newExport(ExportJob::SQL);
ExportAccount::dispatch($job);

return redirect()->route('settings.export.index')
->withStatus(trans('settings.export_submitted'));
}

public function storeJson()
{
$job = $this->newExport(ExportJob::JSON);
ExportAccount::dispatch($job);

return redirect()->route('settings.export.index')
->withStatus(trans('settings.export_submitted'));

}

Dispatch

1
2
3
4
5
// framework/src/Illuminate/Foundation/Bus/Dispatchable.php 
public static function dispatch(...$arguments)
{
return new PendingDispatch(new static(...$arguments));
}

PendingDispatch

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
// framework/src/Illuminate/Foundation/Bus/PendingDispatch.php 
// 提供了一個額外的介面,讓使用者可以更方便地調用 Job 物件的方法。同時,在物件的銷毀時刻,
// PendingDispatch 會根據 $this->afterResponse 屬性來決定要如何分派 $this->job。
namespace Illuminate\Foundation\Bus;

use Illuminate\Bus\UniqueLock;
use Illuminate\Container\Container;
use Illuminate\Contracts\Bus\Dispatcher;
use Illuminate\Contracts\Cache\Repository as Cache;
use Illuminate\Contracts\Queue\ShouldBeUnique;

class PendingDispatch
{
protected $job;

protected $afterResponse = false;

public function __construct($job)
{
$this->job = $job;
}

public function onConnection($connection)
{
$this->job->onConnection($connection);

return $this;
}

public function onQueue($queue)
{
$this->job->onQueue($queue);

return $this;
}

public function allOnConnection($connection)
{
$this->job->allOnConnection($connection);

return $this;
}

public function allOnQueue($queue)
{
$this->job->allOnQueue($queue);

return $this;
}

public function delay($delay)
{
$this->job->delay($delay);

return $this;
}

public function afterCommit()
{
$this->job->afterCommit();

return $this;
}

public function beforeCommit()
{
$this->job->beforeCommit();

return $this;
}

public function chain($chain)
{
$this->job->chain($chain);

return $this;
}

public function afterResponse()
{
$this->afterResponse = true;

return $this;
}

// 實現對任務調度執行的控制,確保同一個唯一的任務在同一時間只會被調度執行一次。
// 返回true,則表示當前任務可以被調度執行,否則返回false,表示該任務已經被另一個進程或線程佔用了
protected function shouldDispatch()
{
if (! $this->job instanceof ShouldBeUnique) {
return true;
}

return (new UniqueLock(Container::getInstance()->make(Cache::class)))
->acquire($this->job);
}

// $pendingDispatch 可以透過 __call 方法動態調用 $job 實例上的任何方法
public function __call($method, $parameters)
{
$this->job->{$method}(...$parameters);

return $this;
}
// 任務調度的判斷
public function __destruct()
{
if (! $this->shouldDispatch()) {
return;
} elseif ($this->afterResponse) {
app(Dispatcher::class)->dispatchAfterResponse($this->job);
} else {
app(Dispatcher::class)->dispatch($this->job);
}
}
}

成功通知

發信notify

1
2
3
4
5
6
7
8
9
// monica/app/Models/Account/ExportJob.php 
public function end(): void
{
$this->status = self::EXPORT_DONE;
$this->ended_at = now();
$this->save();

$this->user->notify(new ExportAccountDone($this));
}

ExportAccountDone

1
2
3
4
5
6
7
8
9
10
11
12
13
// monica/app/Notifications/ExportAccountDone.php 
public function toMail(User $user): MailMessage
{
$date = Carbon::parse($this->exportJob->created_at)
->setTimezone($user->timezone);
// 成功、主題、歡迎詞、描述、下載連結
return (new MailMessage)
->success()
->subject(trans('mail.export_title'))
->greeting(trans('mail.greetings', ['username' => $user->first_name]))
->line(trans('mail.export_description', ['date' => DateHelper::getShortDate($date)]))
->action(trans('mail.export_download'), route('settings.export.index'));
}

下載資源

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// monica/app/Http/Controllers/Settings/ExportController.php 
public function download(Request $request, string $uuid)
{
// 查詢第一筆紀錄
$job = ExportJob::where([
'account_id' => auth()->user()->account_id,
'user_id' => auth()->user()->id,
'uuid' => $uuid,
])->firstOrFail();

// 未完成
if ($job->status !== ExportJob::EXPORT_DONE) {
return redirect()->route('settings.export.index')
->withErrors(trans('settings.export_not_done'));
}
$disk = StorageHelper::disk($job->location);

// 返回請求資料
return $disk->response($job->filename,
"monica.{$job->type}",
[
'Content-Type' => "application/{$job->type}; charset=utf-8",
'Content-Disposition' => "attachment; filename=monica.{$job->type}",
]
);
}
]]>
+ Monica 是一個開源專案,用於組織和記錄與親人的互動。又稱 PRM,個人關係管理。可將其視為您朋友或家人的 CRM,本文會介紹感興趣的功能,API、數據導出、OAuth、以及 issue。

Monica’s vision is to help people have more meaningful relationships.
幫助人們建立有意義的關係

主打"關係管理",相較市面成熟的社交產品(如 Facebook),其定位特別,替人脈建立一個管理後台,還記得大學時參加幹訓、社團迎新,認識各社團幹部,常忘記小細節,此產品便能很好地解決這個問題,基於興趣,我也作為翻譯貢獻者,協助 monica 文件繁體中文的在地化,具體參考chienniman/monica
本文會介紹API授權(個人使用、開放授權),數據導出、社群討論issue,也會同時附上以上功能的原始碼分析,深入淺出的介紹設計模式在本專案的應用。

執行&部署

1
2
3
4
PHP 8.1+
HTTP server with PHP support (eg: Apache, Nginx, Caddy)
Composer
MySQL
1
2
Platform.sh
Heroku

官方文件提到,構建專案程式需要 1.5GB RAM 以上,在 GCP 開便宜的 n1-standard-1,每月最少也要 600 台幣

Authentication

在 Monica 中,OAuth 2.0 與個人訪問令牌是兩種不同的身份驗證機制,但它們都用於授權 API 訪問。
OAuth 2.0 是一種標準的開放授權協議,允許用戶在 Monica 上授權第三方應用程序訪問數據,不需要將用戶名和密碼提供給該應用程序。當用戶通過 OAuth 2.0 授權授權應用程序時,該應用程序會收到一個訪問令牌,以便它可以代表用戶訪問 Monica API。
個人訪問令牌則是一種基於 Monica 賬戶的令牌,允許應用程序代表用戶訪問 Monica API。這意味著,當用戶提供他們的個人訪問令牌給應用程序時,該應用程序就可以代表該用戶訪問 API,就像它擁有 OAuth 2.0 訪問令牌一樣。
雖然這兩種令牌都可以用於授權 API 訪問,但它們的使用方式略有不同。 OAuth 2.0 是一種標準的開放授權協議,允許用戶授權第三方應用程序訪問其數據。個人訪問令牌則是一種在 Monica 內部生成的令牌,只能由用戶本人使用。在大多數情況下,建議使用 OAuth 2.0,因為它是更安全和更靈活的身份驗證協議。

個人驗證授權

1
curl -H "Authorization: Bearer Personal access token" https://app.monicahq.com/api

個人驗證令牌(personal-access-token)


將 token 放在 postmon 的 Authorization

postman測試

開放授權(OAuth)

monica 也提供 OAuth 方式驗證 API,向伺服器發起驗證請求,跳出授權允許視窗,取得 Access Token,之後請求夾帶令牌訪問保護資源

流程

Postmon


配置 postmon 參數,將 Callback URL 填入 monica 後台 API,Token name、Client ID、Client Secret 填入 postmon

授權請求


postmon 會跳出授權請求,允許後核發 Access Token、Refresh Token,點擊使用後自動帶入 Authorization Token 欄位

測試請求


The OAuth 2.0 Authorization Framework: Bearer Token Usage
monica-api 文件

第三方登入

官方託管 monica 支持 OAuth API,卻不支持 Facebook、Google 第三方登入,主流的平台為提升用戶體驗,通常會支持,疑惑地查找社群討論發現

degan6 提出 OAuth 登入的 pull request,但被主要開發者拒絕了

1.不想要支持有疑慮的第三方登入(Facebook 疑似洩漏個資事件)
2.官方託管已經移除大多數的追蹤程式碼

數據導出

monica 能輸出聯絡人vCard,使用者Sql、Json 等,相當便利,數據輸出需較長時間處理,隊列任務被存儲在數據庫,在多個請求之間共享任務。當任務被添加到隊列,被插入到表中,等待被執行。Laravel會跟蹤任務的狀態,未處理、處理中、已處理、失敗。
Laravel預設使用同步隊列(sync),保證實時、穩定性,方便進行開發與測試,但對於大量、耗時任務,同步處理會阻塞主線程,因此不適合高併發場景。

vCard


vCard 是電子名片的文件格式標準。它一般附加在電子郵件之後,但也可以用於其它場合(如在網際網路上相互交換)。vCard 可包含的信息有:姓名、地址資訊、電話號碼、URL,logo,相片等。

Routes

1
2
// monica/routes/web.php 
Route::get('/people/{contact}/vcard', 'ContactsController@vcard')->name('vcard');

ContactsController

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// monica/app/Http/Controllers/ContactsController.php
// 依賴注入:Contact、ExportVCard、Str和LocaleHelper通過依賴注入。
public function vCard(Contact $contact)
{
// 禁用 Debugbar 避免在下載 vCard 時,偵錯列(debugbar)出現在輸出中
if (config('app.debug') && class_exists('\Barryvdh\Debugbar\Facade')) {
Debugbar::disable();
}
// Laravel 中的全域輔助函數,用於從應用程式服務容器中取回特定的服務實例
$vcard = app(ExportVCard::class)->execute([
'account_id' => auth()->user()->account_id,
'contact_id' => $contact->id,
]);
// response 函數將 $vcard 序列化後的 VCard 字符串作為內容,設置 'Content-type' 標頭為 'text/x-vcard'
// 表示傳輸的內容是 VCard 格式。同時,設置 'Content-Disposition' 標頭為 'attachment;
// filename='.Str::slug($contact->name, '-', LocaleHelper::getLang()).'.vcf'
// 表示將其作為下載文件附件發送給用戶端,並將文件名設置為聯絡人的名稱轉換為 slug 格式後加上 .vcf 的檔名
return response($vcard->serialize())
->header('Content-type', 'text/x-vcard')
->header('Content-Disposition', 'attachment; filename='.Str::slug($contact->name, '-', LocaleHelper::getLang()).'.vcf');
}

Sql & Json導出

Routes

1
2
3
// monica/routes/web.php 
Route::post('/settings/exportToSql', 'Settings\\ExportController@storeSQL')->name('export.store.sql');
Route::post('/settings/exportToJson', 'Settings\\ExportController@storeJson')->name('export.store.json');

ExportJob

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
// monica/app/Models/Account/ExportJob.php 
namespace App\Models\Account;

use App\Traits\HasUuid;
use App\Models\User\User;
use Illuminate\Database\Eloquent\Model;
use App\Notifications\ExportAccountDone;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Factories\HasFactory;

class ExportJob extends Model
{
use HasUuid, HasFactory;

public const EXPORT_TODO = 'todo';
public const EXPORT_DOING = 'doing';
public const EXPORT_DONE = 'done';
public const EXPORT_FAILED = 'failed';

public const SQL = 'sql';

public const JSON = 'json';

protected $fillable = [
'uuid',
'account_id',
'user_id',
'type',
'status',
'filesystem',
'filename',
'started_at',
'ended_at',
];

protected $guarded = ['id'];

protected $dates = [
'started_at',
'ended_at',
];

public function account()
{
return $this->belongsTo(Account::class);
}

public function user()
{
return $this->belongsTo(User::class);
}

public function start(): void
{
$this->status = self::EXPORT_DOING;
$this->started_at = now();
$this->save();
}

// 發信通知
public function end(): void
{
$this->status = self::EXPORT_DONE;
$this->ended_at = now();
$this->save();

$this->user->notify(new ExportAccountDone($this));
}
}

ExportController

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
// monica/app/Http/Controllers/Settings/ExportController.php
private function newExport(string $type): ExportJob
{
$exports = ExportJob::where([
'account_id' => auth()->user()->account_id,
'user_id' => auth()->user()->id,
])
->orderBy('created_at')
->get();
// 輸出任務總量超過最大配置,刪除最舊的任務
if ($exports->count() >= config('monica.export_size')) {
$job = $exports->first();
try {
if ($job->filename !== null) {
StorageHelper::disk($job->location)
->delete($job->filename);
}
} finally {
// 確保釋放資源,避免內存洩漏、資源浪費
$job->delete();
}
}
// 回傳剛建立的實例資料
return ExportJob::create([
'account_id' => auth()->user()->account_id,
'user_id' => auth()->user()->id,
'type' => $type,
]);
}

public function storeSql()
{
$job = $this->newExport(ExportJob::SQL);
ExportAccount::dispatch($job);

return redirect()->route('settings.export.index')
->withStatus(trans('settings.export_submitted'));
}

public function storeJson()
{
$job = $this->newExport(ExportJob::JSON);
ExportAccount::dispatch($job);

return redirect()->route('settings.export.index')
->withStatus(trans('settings.export_submitted'));

}

Dispatch

1
2
3
4
5
// framework/src/Illuminate/Foundation/Bus/Dispatchable.php 
public static function dispatch(...$arguments)
{
return new PendingDispatch(new static(...$arguments));
}

PendingDispatch

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
// framework/src/Illuminate/Foundation/Bus/PendingDispatch.php 
// 提供了一個額外的介面,讓使用者可以更方便地調用 Job 物件的方法。同時,在物件的銷毀時刻,
// PendingDispatch 會根據 $this->afterResponse 屬性來決定要如何分派 $this->job。
namespace Illuminate\Foundation\Bus;

use Illuminate\Bus\UniqueLock;
use Illuminate\Container\Container;
use Illuminate\Contracts\Bus\Dispatcher;
use Illuminate\Contracts\Cache\Repository as Cache;
use Illuminate\Contracts\Queue\ShouldBeUnique;

class PendingDispatch
{
protected $job;

protected $afterResponse = false;

public function __construct($job)
{
$this->job = $job;
}

public function onConnection($connection)
{
$this->job->onConnection($connection);

return $this;
}

public function onQueue($queue)
{
$this->job->onQueue($queue);

return $this;
}

public function allOnConnection($connection)
{
$this->job->allOnConnection($connection);

return $this;
}

public function allOnQueue($queue)
{
$this->job->allOnQueue($queue);

return $this;
}

public function delay($delay)
{
$this->job->delay($delay);

return $this;
}

public function afterCommit()
{
$this->job->afterCommit();

return $this;
}

public function beforeCommit()
{
$this->job->beforeCommit();

return $this;
}

public function chain($chain)
{
$this->job->chain($chain);

return $this;
}

public function afterResponse()
{
$this->afterResponse = true;

return $this;
}

// 實現對任務調度執行的控制,確保同一個唯一的任務在同一時間只會被調度執行一次。
// 返回true,則表示當前任務可以被調度執行,否則返回false,表示該任務已經被另一個進程或線程佔用了
protected function shouldDispatch()
{
if (! $this->job instanceof ShouldBeUnique) {
return true;
}

return (new UniqueLock(Container::getInstance()->make(Cache::class)))
->acquire($this->job);
}

// $pendingDispatch 可以透過 __call 方法動態調用 $job 實例上的任何方法
public function __call($method, $parameters)
{
$this->job->{$method}(...$parameters);

return $this;
}
// 任務調度的判斷
public function __destruct()
{
if (! $this->shouldDispatch()) {
return;
} elseif ($this->afterResponse) {
app(Dispatcher::class)->dispatchAfterResponse($this->job);
} else {
app(Dispatcher::class)->dispatch($this->job);
}
}
}

成功通知

發信notify

1
2
3
4
5
6
7
8
9
// monica/app/Models/Account/ExportJob.php 
public function end(): void
{
$this->status = self::EXPORT_DONE;
$this->ended_at = now();
$this->save();

$this->user->notify(new ExportAccountDone($this));
}

ExportAccountDone

1
2
3
4
5
6
7
8
9
10
11
12
13
// monica/app/Notifications/ExportAccountDone.php 
public function toMail(User $user): MailMessage
{
$date = Carbon::parse($this->exportJob->created_at)
->setTimezone($user->timezone);
// 成功、主題、歡迎詞、描述、下載連結
return (new MailMessage)
->success()
->subject(trans('mail.export_title'))
->greeting(trans('mail.greetings', ['username' => $user->first_name]))
->line(trans('mail.export_description', ['date' => DateHelper::getShortDate($date)]))
->action(trans('mail.export_download'), route('settings.export.index'));
}

下載資源

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// monica/app/Http/Controllers/Settings/ExportController.php 
public function download(Request $request, string $uuid)
{
// 查詢第一筆紀錄
$job = ExportJob::where([
'account_id' => auth()->user()->account_id,
'user_id' => auth()->user()->id,
'uuid' => $uuid,
])->firstOrFail();

// 未完成
if ($job->status !== ExportJob::EXPORT_DONE) {
return redirect()->route('settings.export.index')
->withErrors(trans('settings.export_not_done'));
}
$disk = StorageHelper::disk($job->location);

// 返回請求資料
return $disk->response($job->filename,
"monica.{$job->type}",
[
'Content-Type' => "application/{$job->type}; charset=utf-8",
'Content-Disposition' => "attachment; filename=monica.{$job->type}",
]
);
}
]]>
@@ -219,10 +238,10 @@ Authorization - Laravel - Monica + Laravel + OAuth @@ -236,7 +255,7 @@ /(%E6%8A%80%E8%A1%93)%E7%B6%B2%E9%A0%81%E6%89%93%E5%8C%85%E5%A3%93%E7%B8%AE%E7%9A%84%E5%A5%BD%E7%94%A8%E5%B7%A5%E5%85%B7Parcel/ -

說到打包工具,多數人的第一直覺就是Webpack,我也不例外,今天就要介紹一個簡單快速的打包工具Parcel,適用於小型專案的開發。

為何壓縮

伺服器中,會使用壓縮來減少頻寬和傳輸時間,從而提高網站性能和用戶體驗。通常壓縮的是返回給客戶端的HTML、CSS、JavaScript、圖像等靜態資源文件。透過減少文件大小。

網頁伺服器會使用一些壓縮算法,例如gzip和deflate,將靜態資源文件壓縮成壓縮包,然後在將壓縮包傳輸給客戶端。客戶端接收到壓縮包後,會解壓縮文件並顯示頁面。

壓縮技術可以提高網站性能,但壓縮也可能增加服務器的負擔和處理時間。此外,某些瀏覽器不支持特定的壓縮算法,因此需要在服務器端進行相應的配置和優化。

原生性能

Parcel’s JavaScript compiler, CSS transformer, and source maps implementation are written in Rust for maximum performance. It’s 10-20x faster than other JavaScript-based tools!
Parcel’s JavaScript compiler is built on SWC, which handles transpiling JavaScript, JSX, and TypeScript. On top of SWC, Parcel implements dependency collection, bundling, scope hoisting, tree shaking, Node emulation, hot reloading, and more.
Parcel’s CSS transformer and minifier is built in Rust on top of the browser-grade CSS parser used in Firefox. It’s over 100x faster than other JavaScript-based transformers and minifiers.

JavaScript 編譯器、CSS 轉換器和源映射實現是用Rust編寫的,以實現最佳性能。它比其他基於 JavaScript 的工具快 10-20 倍!
Parcel 的 JavaScript 編譯器建立在SWC之上,它處理轉譯 JavaScript、JSX 和 TypeScript。在 SWC 之上,Parcel 實現了依賴收集、捆綁、範圍提升、tree shaking、Node 仿真、熱重載等。
Parcel 的 CSS 轉換器和縮小器是在 Firefox 中使用的瀏覽器級 CSS 解析器之上的 Rust 中構建的。比其他JavaScript 的轉換器和壓縮器快 100 倍以上。

快取

Everything Parcel does is cached – transformation, dependency resolution, bundling, optimizing, and everything in between. This means the dev server restarts instantly, and the same code is never built twice.
Parcel automatically tracks all of the files, configuration, plugins, and dev dependencies that are involved in your build, and granularly invalidates the cache when something changes. It integrates with low-level operating system APIs to determine what files have changed in milliseconds, no matter the project size.

Parcel 所做的一切都被緩存——轉換、依賴解析、捆綁、優化,以及介於兩者之間的一切。這意味著開發伺服器會立即重新啟動,並且永遠不會構建相同的代碼兩次。
自動追蹤構建中所有文件、配置、插件和依賴項,並在變化時使緩存失效。與低階操作系統 API 整合,無論項目大小如何,都可以在幾毫秒內確定哪些文件發生了變化。

安裝

1
npm install --save-dev parcel

配置

1
2
3
4
5
6
7
8
9
10
11
{
"name": "my-project",
"source": "src/index.html",
"scripts": {
"start": "parcel",
"build": "parcel build"
},
"devDependencies": {
"parcel": "latest"
}
}

資料夾

1
2
3
4
5
6
7
8
9
10
my-app/
|- dist/ # 編譯後代碼
| |- index.html # 打包後的 HTML
| |- main.js # 打包後的 JavaScript
|- node_modules/ # 第三方庫
|- src/ # 源碼
| |- index.html # HTML 入口
| |- main.js # JavaScript 入口
|- package.json # 配置
|-.parcel-cache # 打包緩存

開發環境
生產環境

JavaScript

介紹Parcel中js的配置前,先了解ES modules跟 CommonJS 的差異。

載入

ES modules 使用 import 載入模組,而 CommonJS 使用 require 載入模組。ES modules 在運行時進行靜態解析,而 CommonJS 在運行時動態載入。

編譯

ES modules 在編譯時會進行預解析和標記,使得編譯器能夠在編譯時知道哪些模組需要載入,而 CommonJS 則是在運行時動態載入,因此需要進行動態解析和加載,相對於 ES modules 更耗費運行時的資源。

輸出

ES modules 使用 export 輸出模組,而 CommonJS 使用 module.exports 輸出模組。ES modules 可以直接將對象、函數等直接作為輸出,而 CommonJS 必須透過 module.exports 將需要輸出的對象或函數包裝成對象再進行輸出。

結論

總之,ES modules 是一種新的模組化,比起CommonJS,有更好的靜態解析能力,支持標記和預解析,並且可以在編譯時優化。然而,目前在瀏覽器中 ES modules 的支援度還不夠完善,需要透過轉譯或者 polyfill 來實現,而 CommonJS 則是在 Node.js 等環境中得到了廣泛的使用。

ES modules

add.js

1
2
3
export function add(a, b) {
return a + b;
}

sum.js

1
2
3
4
5
import {add} from './add.js';

export function sum(x,y) {
return add(x, y);
}

CommonJS

add.js

1
2
3
exports.add=function(a, b) {
return a + b;
}

sum.js

1
2
3
4
5
const add=require('./add.js');

exports.sum=function(x,y) {
return add(x, y);
}

總結

與Webpack相比,Parcel的生態和功能有限,較難進行進階的設置。因此,在選擇使用Webpack還是Parcel時,需要根據具體需求和技術做出選擇。如果是在簡單項目中快速構建和開發,Parcel可能是一個不錯的選擇;如果需要更高度的客製化和擴展性,Webpack可能更符合需求。

參考資料

Parcel

]]>
+

說到打包工具,多數人的第一直覺就是Webpack,我也不例外,今天就要介紹一個簡單快速的打包工具Parcel,適用於小型專案的開發。

為何壓縮

伺服器中,會使用壓縮來減少頻寬和傳輸時間,從而提高網站性能和用戶體驗。通常壓縮的是返回給客戶端的HTML、CSS、JavaScript、圖像等靜態資源文件。透過減少文件大小。

網頁伺服器會使用一些壓縮算法,例如gzip和deflate,將靜態資源文件壓縮成壓縮包,然後在將壓縮包傳輸給客戶端。客戶端接收到壓縮包後,會解壓縮文件並顯示頁面。

壓縮技術可以提高網站性能,但壓縮也可能增加服務器的負擔和處理時間。此外,某些瀏覽器不支持特定的壓縮算法,因此需要在服務器端進行相應的配置和優化。

原生性能

Parcel’s JavaScript compiler, CSS transformer, and source maps implementation are written in Rust for maximum performance. It’s 10-20x faster than other JavaScript-based tools!
Parcel’s JavaScript compiler is built on SWC, which handles transpiling JavaScript, JSX, and TypeScript. On top of SWC, Parcel implements dependency collection, bundling, scope hoisting, tree shaking, Node emulation, hot reloading, and more.
Parcel’s CSS transformer and minifier is built in Rust on top of the browser-grade CSS parser used in Firefox. It’s over 100x faster than other JavaScript-based transformers and minifiers.

JavaScript 編譯器、CSS 轉換器和源映射實現是用Rust編寫的,以實現最佳性能。它比其他基於 JavaScript 的工具快 10-20 倍!
Parcel 的 JavaScript 編譯器建立在SWC之上,它處理轉譯 JavaScript、JSX 和 TypeScript。在 SWC 之上,Parcel 實現了依賴收集、捆綁、範圍提升、tree shaking、Node 仿真、熱重載等。
Parcel 的 CSS 轉換器和縮小器是在 Firefox 中使用的瀏覽器級 CSS 解析器之上的 Rust 中構建的。比其他JavaScript 的轉換器和壓縮器快 100 倍以上。

快取

Everything Parcel does is cached – transformation, dependency resolution, bundling, optimizing, and everything in between. This means the dev server restarts instantly, and the same code is never built twice.
Parcel automatically tracks all of the files, configuration, plugins, and dev dependencies that are involved in your build, and granularly invalidates the cache when something changes. It integrates with low-level operating system APIs to determine what files have changed in milliseconds, no matter the project size.

Parcel 所做的一切都被緩存——轉換、依賴解析、捆綁、優化,以及介於兩者之間的一切。這意味著開發伺服器會立即重新啟動,並且永遠不會構建相同的代碼兩次。
自動追蹤構建中所有文件、配置、插件和依賴項,並在變化時使緩存失效。與低階操作系統 API 整合,無論項目大小如何,都可以在幾毫秒內確定哪些文件發生了變化。

安裝

1
npm install --save-dev parcel

配置

1
2
3
4
5
6
7
8
9
10
11
{
"name": "my-project",
"source": "src/index.html",
"scripts": {
"start": "parcel",
"build": "parcel build"
},
"devDependencies": {
"parcel": "latest"
}
}

資料夾

1
2
3
4
5
6
7
8
9
10
my-app/
|- dist/ # 編譯後代碼
| |- index.html # 打包後的 HTML
| |- main.js # 打包後的 JavaScript
|- node_modules/ # 第三方庫
|- src/ # 源碼
| |- index.html # HTML 入口
| |- main.js # JavaScript 入口
|- package.json # 配置
|-.parcel-cache # 打包緩存

開發環境
生產環境

JavaScript

介紹Parcel中js的配置前,先了解ES modules跟 CommonJS 的差異。

載入

ES modules 使用 import 載入模組,而 CommonJS 使用 require 載入模組。ES modules 在運行時進行靜態解析,而 CommonJS 在運行時動態載入。

編譯

ES modules 在編譯時會進行預解析和標記,使得編譯器能夠在編譯時知道哪些模組需要載入,而 CommonJS 則是在運行時動態載入,因此需要進行動態解析和加載,相對於 ES modules 更耗費運行時的資源。

輸出

ES modules 使用 export 輸出模組,而 CommonJS 使用 module.exports 輸出模組。ES modules 可以直接將對象、函數等直接作為輸出,而 CommonJS 必須透過 module.exports 將需要輸出的對象或函數包裝成對象再進行輸出。

結論

總之,ES modules 是一種新的模組化,比起CommonJS,有更好的靜態解析能力,支持標記和預解析,並且可以在編譯時優化。然而,目前在瀏覽器中 ES modules 的支援度還不夠完善,需要透過轉譯或者 polyfill 來實現,而 CommonJS 則是在 Node.js 等環境中得到了廣泛的使用。

ES modules

add.js

1
2
3
export function add(a, b) {
return a + b;
}

sum.js

1
2
3
4
5
import {add} from './add.js';

export function sum(x,y) {
return add(x, y);
}

CommonJS

add.js

1
2
3
exports.add=function(a, b) {
return a + b;
}

sum.js

1
2
3
4
5
const add=require('./add.js');

exports.sum=function(x,y) {
return add(x, y);
}

總結

與Webpack相比,Parcel的生態和功能有限,較難進行進階的設置。因此,在選擇使用Webpack還是Parcel時,需要根據具體需求和技術做出選擇。如果是在簡單項目中快速構建和開發,Parcel可能是一個不錯的選擇;如果需要更高度的客製化和擴展性,Webpack可能更符合需求。

參考資料

Parcel

]]>
@@ -263,7 +282,7 @@ /(%E6%8A%80%E8%A1%93)30%E7%A7%92%E8%A7%A3%E6%B1%BADcard%E5%BD%88%E8%B7%B3%E8%A6%96%E7%AA%97/ - 可以不要一直叫我登入嗎

有時在網路上看到有趣的 Dcard 文章,好奇點進去,看留言時卻跳出討厭的登入視窗,這篇文章會示範如何用開發者工具在 30 秒內關閉

  1. 點擊 F12,開發者工具

  2. 找到彈跳視窗根元素(最外層,屬性 tabindex=”0”),點滑鼠右鍵,刪除元素,這時候就可以看到乾淨漂亮的頁面了~但是還是不能滾動

  3. 往上滑找到 body 元素,element 屬性加上 overflow:scroll

  4. 大功告成,不需要打帳密了

全自動執行

做成 Chrome Extension,這裡提供思路,封裝實作可以參考這篇文章

1
2
3
4
5
6
7
window.addEventListener('load', function() {
const popup = document.getElementById({modal--id});
if (popup) {
popup.remove();
document.body.style.overflow = 'scroll';
}
});

免責聲明

本文僅為客戶端提供教學示範之用,請勿用於任何影響網頁正常運作的技術,否則將自行承擔相應法律責任。

]]>
+ 可以不要一直叫我登入嗎

有時在網路上看到有趣的 Dcard 文章,好奇點進去,看留言時卻跳出討厭的登入視窗,這篇文章會示範如何用開發者工具在 30 秒內關閉

  1. 點擊 F12,開發者工具

  2. 找到彈跳視窗根元素(最外層,屬性 tabindex=“0”),點滑鼠右鍵,刪除元素,這時候就可以看到乾淨漂亮的頁面了~但是還是不能滾動

  3. 往上滑找到 body 元素,element 屬性加上 overflow:scroll

  4. 大功告成,不需要打帳密了

全自動執行

做成 Chrome Extension,這裡提供思路,封裝實作可以參考這篇文章

1
2
3
4
5
6
7
window.addEventListener('load', function() {
const popup = document.getElementById({modal--id});
if (popup) {
popup.remove();
document.body.style.overflow = 'scroll';
}
});

免責聲明

本文僅為客戶端提供教學示範之用,請勿用於任何影響網頁正常運作的技術,否則將自行承擔相應法律責任。

]]>
@@ -288,7 +307,7 @@ /(%E6%8A%80%E8%A1%93)%E8%A3%BD%E4%BD%9C%E8%87%AA%E5%8B%95%E6%8E%92%E7%A8%8B%E7%9A%84YoubikeLineBot/ - 關於騎腳踏車上班

Youbike 通勤上下班,趕到公司樓下卻發現沒有空位,只能花費雙倍路程時間步行到上一站,搜尋可行的解決方案,別人製作的 站點地圖是不錯的解決方案,但對壓線出門的懶人不是最佳解,重複的查詢、比較、紀錄相當多餘,真正能解決痛點的是固定時間、主動通知、快速查詢工具。
以 Node.js開發的 bot,邏輯在index.js完整原始碼

特點

  • 自動化查詢
  • 部署Render雲服務
  • 排程每日通知

SDK

其他語言參考Official SDKs,官方提供

  • Java
  • PHP
  • Go
  • Perl
  • Ruby
  • Python
  • Node.js

本地

1
git clone https://github.com/chienniman/YouBikeNotify-Bot.git
1
npm install
1
mkdir .env

環境變數&金鑰

Cron

1
npm install --save node-cron

臺中交通資訊 API

上網搜了一下發現臺中交通資訊 API 整合的相當不錯,Swagger 的文件架構清晰,井然有序,這邊給個讚,台中路面狀況如果也可以就謝天謝地了
臺中交通資訊 API

LINE Developers

首先要先創建一個 LINE Developers 帳號
註冊網址

LINE Bot channel

登入後點選 Create new channel 創建新的 LINE Bot 頻道,並且填寫頻道相關資訊(例如:頻道名稱、頻道圖片、類型等等)。

ngrok

ngrok 做為一個轉發的伺服器,他可以把外界的請求轉發到你指定的 Port,使用的背景原理是連接到 ngrok 雲端伺服器,將你本機指定的地址公開,再將由 ngrok 一串公開的網址來存取內容。他的優點是快速而且還提供了 https 的服務讓你使用上更安全,甚至你還可以設置密碼保護。

ref-[Day-37] 使用 ngrok 讓外網連接你的 API

安裝

ngrok

執行

windows,雙擊 exe

linux, cd ngrok

1
ngrok.exe http {port}

映射

1
2
<!-- 雲端=>本地 -->
Forwarding https://xxxxxx.ngrok.io -> localhost:{port}

資安

沒有正確地設定 ngrok,防火牆、密碼,可能導致安全風險,使用完記得ctrl+c退出

驗證失敗

ngrok 運行 500,terminal 顯示 404,因為 token 沒設定好

部署雲端

官方文件nodejs-on-rende

1.設定render.yaml
2.新增 Web Service
3.Public Git repository
4.設定姓名、環境、區域
5.編譯部屬成功
deploy-success

免費限制

Free instance types are not available for Private Services, Background Workers, or Cron Jobs.

Web Services on the free instance type are automatically spun down after 15 minutes of inactivity. When a new request for a free service comes in, Render spins it up again so it can process the request.
This can cause a response delay of up to 30 seconds for the first request that comes in after a period of inactivity.

  • 本地伺服器可自動排程,但 render 雲的免費計畫不支援
  • 超過 15 分鐘沒有活動,伺服器會自動停止,直到新的請求,造成延遲響應。

心得

youbike 地圖相當方便,但是查詢、紀錄、比較等重複性工作仍可優化,都說科技始終來自惰性,有了排程查詢機器人後只需要被動等待通知,但缺點也是相當明顯,不穩定的響應(1 秒~6 分鐘),注定讓免費計畫只能作為實驗用途,很少使用者能接受超過 5 秒的等待,會不會升級成付費版本目前還在觀察中。

]]>
+ 關於騎腳踏車上班

Youbike 通勤上下班,趕到公司樓下卻發現沒有空位,只能花費雙倍路程時間步行到上一站,搜尋可行的解決方案,別人製作的 站點地圖是不錯的解決方案,但對壓線出門的懶人不是最佳解,重複的查詢、比較、紀錄相當多餘,真正能解決痛點的是固定時間、主動通知、快速查詢工具。
以 Node.js開發的 bot,邏輯在index.js完整原始碼

特點

  • 自動化查詢
  • 部署Render雲服務
  • 排程每日通知

SDK

其他語言參考Official SDKs,官方提供

  • Java
  • PHP
  • Go
  • Perl
  • Ruby
  • Python
  • Node.js

本地

1
git clone https://github.com/chienniman/YouBikeNotify-Bot.git
1
npm install
1
mkdir .env

環境變數&金鑰

Cron

1
npm install --save node-cron

臺中交通資訊 API

上網搜了一下發現臺中交通資訊 API 整合的相當不錯,Swagger 的文件架構清晰,井然有序,這邊給個讚,台中路面狀況如果也可以就謝天謝地了
臺中交通資訊 API

LINE Developers

首先要先創建一個 LINE Developers 帳號
註冊網址

LINE Bot channel

登入後點選 Create new channel 創建新的 LINE Bot 頻道,並且填寫頻道相關資訊(例如:頻道名稱、頻道圖片、類型等等)。

ngrok

ngrok 做為一個轉發的伺服器,他可以把外界的請求轉發到你指定的 Port,使用的背景原理是連接到 ngrok 雲端伺服器,將你本機指定的地址公開,再將由 ngrok 一串公開的網址來存取內容。他的優點是快速而且還提供了 https 的服務讓你使用上更安全,甚至你還可以設置密碼保護。

ref-[Day-37] 使用 ngrok 讓外網連接你的 API

安裝

ngrok

執行

windows,雙擊 exe

linux, cd ngrok

1
ngrok.exe http {port}

映射

1
2
<!-- 雲端=>本地 -->
Forwarding https://xxxxxx.ngrok.io -> localhost:{port}

資安

沒有正確地設定 ngrok,防火牆、密碼,可能導致安全風險,使用完記得ctrl+c退出

驗證失敗

ngrok 運行 500,terminal 顯示 404,因為 token 沒設定好

部署雲端

官方文件nodejs-on-rende

1.設定render.yaml
2.新增 Web Service
3.Public Git repository
4.設定姓名、環境、區域
5.編譯部屬成功
deploy-success

免費限制

Free instance types are not available for Private Services, Background Workers, or Cron Jobs.

Web Services on the free instance type are automatically spun down after 15 minutes of inactivity. When a new request for a free service comes in, Render spins it up again so it can process the request.
This can cause a response delay of up to 30 seconds for the first request that comes in after a period of inactivity.

  • 本地伺服器可自動排程,但 render 雲的免費計畫不支援
  • 超過 15 分鐘沒有活動,伺服器會自動停止,直到新的請求,造成延遲響應。

心得

youbike 地圖相當方便,但是查詢、紀錄、比較等重複性工作仍可優化,都說科技始終來自惰性,有了排程查詢機器人後只需要被動等待通知,但缺點也是相當明顯,不穩定的響應(1 秒~6 分鐘),注定讓免費計畫只能作為實驗用途,很少使用者能接受超過 5 秒的等待,會不會升級成付費版本目前還在觀察中。

]]>
@@ -321,7 +340,7 @@ /(%E6%8A%80%E8%A1%93)%E6%B7%BA%E8%AB%87%E4%BC%BA%E6%9C%8D%E5%99%A8%E7%9A%84%E6%8E%88%E6%AC%8A%E3%80%81%E9%A9%97%E8%AD%89/ - Authentication

驗證,告訴伺服器登入者是其所聲稱的使用者,以遊戲登入舉例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
+------------------------+        
| 遊戲客戶端啟動 |
+-----------+------------+
|
| 向遊戲伺服器發送認證請求
|
+-----------v------------+
| 遊戲伺服器進行認證 |
+-----------+------------+
|
| 驗證玩家帳號和密碼是否正確、權限(有無鎖帳號)
|
+-----------v------------+
| 確認帳號和密碼正確 |
+-----------+------------+
|
| 允許進入遊戲伺服器
|
+-----------v------------+
| 排隊進入遊戲 |
+------------------------+

Authorization

當玩家通過驗證進入遊戲伺服器後,伺服器會根據玩家的帳戶資料進行授權,假設想要2023的年槍,紫炫流光,就得向伺服器獲得授權,買解碼器、黑市,才能解鎖新武器。

簡單舉例

1
2
購買武器 -> 檢查是否有足夠點數 -> 扣款授權 -> 武器授權 -> 成功購買 

每個玩家客戶端都有全部種類的武器,來自於每次的更新檔,是為了提升遊戲體驗,總不能撿到新槍再下載吧,因此授權只是向伺服器請求,解鎖不能使用的武器。

Https Authentication(Basic)

一種HTTP驗證機制,Base64將用戶名和密碼進行編碼,然後在HTTP請求中以Authorization標頭的形式傳送。簡單來說,當使用者輸入用戶名和密碼時,這些數據將被編碼並包含在HTTP請求中,伺服器收到請求後會解碼這些數據並進行身份驗證。

jigsaw demo

jigsaw.w3.org測試網址

1
2
ac:guest
pw:guest
  • 伺服器檢查在Header裡的Authorization欄位,規格應為 Authorization: Basic <value>
  • 此時因為沒有Authorization並沒有資料,server按照約定會回傳401 status code並在Header上加上 WWW-Authenticate: Basic realm="<value>"
  • client當發現得到以上的回應後,會出現一個給予使用者輸入用戶名稱及密碼的地方
  • client將用戶名稱跟密碼做成base64(username:password)
  • client將資料放到Header: Authorization: base64(username:password)

先生你誰?-身分驗證Authentication (Basic, token, JWT)

把header的authentication取出base64解碼可以看到正好是輸入的帳密

1
base64(username:password)

Digest:

摘要訪問認證是一種協議規定的Web伺服器用來同網頁瀏覽器進行認證信息協商的方法。它在密碼發出前,先對其應用哈希函數,相對於HTTP基本認證發送明文而言,更安全。
https://zh.wikipedia.org/zh-tw/HTTP%E6%91%98%E8%A6%81%E8%AE%A4%E8%AF%81

  • 客戶端向服務器發送請求。
  • 服務器回復401和WWW-Authenticate,nonce(服務器生成的隨機字符串,防止重放攻擊)。
    1
    2
    3
    4
    www-authenticate: 
    Digest realm="test",
    domain="/HTTP/Digest",
    nonce="e67010901fb034b2e0e0c9e0c1f451d8"
  • 客戶端使用用戶名、領域和密碼計算出HA1值,使用請求方式和請求URI計算出HA2值。
  • 客戶端使用HA1、nonce和HA2計算出響應值,加到“Authorization”的header。
    1
    2
    3
    HA1 = MD5(username:realm:password)
    HA2 = MD5(method:digestURI)
    response = MD5(HA1:nonce:HA2)
  • 服務器使用相同的計算方式驗證。如果正確,服務器會返回請求的資源,否則,返回401未授權或其他錯誤狀態碼,客戶端必須重新進行身份驗證。
]]>
+ Authentication

驗證,告訴伺服器登入者是其所聲稱的使用者,以遊戲登入舉例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
+------------------------+        
| 遊戲客戶端啟動 |
+-----------+------------+
|
| 向遊戲伺服器發送認證請求
|
+-----------v------------+
| 遊戲伺服器進行認證 |
+-----------+------------+
|
| 驗證玩家帳號和密碼是否正確、權限(有無鎖帳號)
|
+-----------v------------+
| 確認帳號和密碼正確 |
+-----------+------------+
|
| 允許進入遊戲伺服器
|
+-----------v------------+
| 排隊進入遊戲 |
+------------------------+

Authorization

當玩家通過驗證進入遊戲伺服器後,伺服器會根據玩家的帳戶資料進行授權,假設想要2023的年槍,紫炫流光,就得向伺服器獲得授權,買解碼器、黑市,才能解鎖新武器。

簡單舉例

1
2
購買武器 -> 檢查是否有足夠點數 -> 扣款授權 -> 武器授權 -> 成功購買 

每個玩家客戶端都有全部種類的武器,來自於每次的更新檔,是為了提升遊戲體驗,總不能撿到新槍再下載吧,因此授權只是向伺服器請求,解鎖不能使用的武器。

Https Authentication(Basic)

一種HTTP驗證機制,Base64將用戶名和密碼進行編碼,然後在HTTP請求中以Authorization標頭的形式傳送。簡單來說,當使用者輸入用戶名和密碼時,這些數據將被編碼並包含在HTTP請求中,伺服器收到請求後會解碼這些數據並進行身份驗證。

jigsaw demo

jigsaw.w3.org測試網址

1
2
ac:guest
pw:guest
  • 伺服器檢查在Header裡的Authorization欄位,規格應為 Authorization: Basic <value>
  • 此時因為沒有Authorization並沒有資料,server按照約定會回傳401 status code並在Header上加上 WWW-Authenticate: Basic realm="<value>"
  • client當發現得到以上的回應後,會出現一個給予使用者輸入用戶名稱及密碼的地方
  • client將用戶名稱跟密碼做成base64(username:password)
  • client將資料放到Header: Authorization: base64(username:password)

先生你誰?-身分驗證Authentication (Basic, token, JWT)

把header的authentication取出base64解碼可以看到正好是輸入的帳密

1
base64(username:password)

Digest:

摘要訪問認證是一種協議規定的Web伺服器用來同網頁瀏覽器進行認證信息協商的方法。它在密碼發出前,先對其應用哈希函數,相對於HTTP基本認證發送明文而言,更安全。
https://zh.wikipedia.org/zh-tw/HTTP%E6%91%98%E8%A6%81%E8%AE%A4%E8%AF%81

  • 客戶端向服務器發送請求。
  • 服務器回復401和WWW-Authenticate,nonce(服務器生成的隨機字符串,防止重放攻擊)。
1
2
3
4
www-authenticate: 
Digest realm="test",
domain="/HTTP/Digest",
nonce="e67010901fb034b2e0e0c9e0c1f451d8"
  • 客戶端使用用戶名、領域和密碼計算出HA1值,使用請求方式和請求URI計算出HA2值。
  • 客戶端使用HA1、nonce和HA2計算出響應值,加到“Authorization”的header。
1
2
3
HA1 = MD5(username:realm:password)
HA2 = MD5(method:digestURI)
response = MD5(HA1:nonce:HA2)
  • 服務器使用相同的計算方式驗證。如果正確,服務器會返回請求的資源,否則,返回401未授權或其他錯誤狀態碼,客戶端必須重新進行身份驗證。
]]>
@@ -350,7 +369,7 @@ /(%E5%BF%83%E5%BE%97)%E8%80%83%E5%8F%96AZ-900%E5%BF%83%E5%BE%97%E5%88%86%E4%BA%AB/ -

筆者於2022/10/29通過AZ900,在此分享,先前在FB看到大推Azure廣告,本身雖以軟體開發為主,但對雲端也深感興趣。

流程

1.聽完線上講座免費拿考試卷 / 自費購買($75美元,印象中)
2.報名線上/實體,自己是去聯成電腦考試
3.考試前要先拍證件照
4.被帶進小房間考試,全程後面有考官盯著
5.印象中寫了30分鐘就交了,當場就知道分數

如何準備

1.寫考古題再去背概念(畫心智圖)
2.youtube/微軟 Doc 掃一次
3.英文準備

範例

考題幾乎都是一個概念的比較,例如混合雲、公共雲、私有雲差別應用,很快就能判斷,但是
中英文翻譯落差,第一眼看到題目可能會愣住,因此建議讀文件&考古都使用英文

選擇題-官方例題

組織會使用哪一種雲端方法來充分利用內部部署技術投資,並在兩個環境之間共用資料和應用程式?

A. 公用雲端
B. 私人雲端
C. 混合式雲端
D. 內部部署資料中心

混合雲:

控制——您的組織可以為需要低延遲的敏感資產或工作負載維護私有基礎架構。
靈活性——您可以在需要時利用公共雲中的額外資源。
成本效益——通過擴展到公共雲的能力,您只需在需要時為額外的計算能力付費。
輕鬆— 過渡到云不必費力,因為您可以逐步遷移 — 隨著時間的推移逐步分階段遷移工

公共雲

公共雲是最常見的雲計算部署類型。雲資源(如服務器和存儲)由第三方雲服務提供商擁有和運營,並通過互聯網交付。使用公共雲,所有硬件、軟件和其他支持基礎設施都由雲提供商擁有和管理。Microsoft Azure 是公共雲的一個示例。

在公共雲中,您與其他組織或云“租戶”共享相同的硬件、存儲和網絡設備,並使用 Web 瀏覽器訪問服務和管理您的帳戶。公共雲部署經常用於提供基於 Web 的電子郵件、在線辦公應用程序、存儲以及測試和開發環境。

優勢:
降低成本——無需購買硬件或軟件,您只需為使用的服務付費。
無需維護——您的服務提供商提供維護。
近乎無限的可擴展性——按需資源可滿足您的業務需求。
高可靠性——龐大的服務器網絡確保不會出現故障。

私有云由一個企業或組織專門使用的雲計算資源組成。私有云可以物理地位於您組織的現場數據中心,也可以由第三方服務提供商託管。但在私有云中,服務和基礎設施始終在私有網絡上維護,硬件和軟件專門用於您的組織。

通過這種方式,私有云可以讓組織更輕鬆地自定義其資源以滿足特定的 IT 要求。私有云通常被政府機構、金融機構和任何其他具有關鍵業務運營的中大型組織所使用,這些組織尋求增強對環境的控制。

私有雲:

更大的靈活性——您的組織可以自定義其云環境以滿足特定的業務需求。
更多控制——資源不與他人共享,因此可以實現更高級別的控制和隱私。
更高的可擴展性——與本地基礎設施相比,私有云通常提供更高的可擴展性。

解答

答案是 C. 混合式雲端。

推薦資源

Microsoft AZ-900 Exam免費考古題

總結

AZ-900都是以簡單快速記憶為主,不需要深度記憶與推理,廣度大於深度,快速掃過的效益比才是最高的,時間不夠可以直接刷考古題,不建議找太舊的。

可參考當次的考試指南,這樣比較有方向,網路考古題有些答案是錯的,而且分歧極大,遇到這種題目都建議直接找官方文檔。

不過要是像我一樣前天晚上才準備了話建議是直接pass,還記得走出考場的時候只花了一半時間,壓線通過,監考官還疑惑地問說今天怎麼這麼多人都來考,完成後必須在登記表上
簽退,掃了一下當天大概有4個來考,並不是每一位都通過。

https://azure.microsoft.com/en-gb/resources/cloud-computing-dictionary/what-is-iaas/#faq

]]>
+

筆者於2022/10/29通過AZ900,在此分享,先前在FB看到大推Azure廣告,本身雖以軟體開發為主,但對雲端也深感興趣。

流程

1.聽完線上講座免費拿考試卷 / 自費購買($75美元,印象中)
2.報名線上/實體,自己是去聯成電腦考試
3.考試前要先拍證件照
4.被帶進小房間考試,全程後面有考官盯著
5.印象中寫了30分鐘就交了,當場就知道分數

如何準備

1.寫考古題再去背概念(畫心智圖)
2.youtube/微軟 Doc 掃一次
3.英文準備

範例

考題幾乎都是一個概念的比較,例如混合雲、公共雲、私有雲差別應用,很快就能判斷,但是
中英文翻譯落差,第一眼看到題目可能會愣住,因此建議讀文件&考古都使用英文

選擇題-官方例題

組織會使用哪一種雲端方法來充分利用內部部署技術投資,並在兩個環境之間共用資料和應用程式?

A. 公用雲端
B. 私人雲端
C. 混合式雲端
D. 內部部署資料中心

混合雲:

控制——您的組織可以為需要低延遲的敏感資產或工作負載維護私有基礎架構。
靈活性——您可以在需要時利用公共雲中的額外資源。
成本效益——通過擴展到公共雲的能力,您只需在需要時為額外的計算能力付費。
輕鬆— 過渡到云不必費力,因為您可以逐步遷移 — 隨著時間的推移逐步分階段遷移工

公共雲

公共雲是最常見的雲計算部署類型。雲資源(如服務器和存儲)由第三方雲服務提供商擁有和運營,並通過互聯網交付。使用公共雲,所有硬件、軟件和其他支持基礎設施都由雲提供商擁有和管理。Microsoft Azure 是公共雲的一個示例。

在公共雲中,您與其他組織或云“租戶”共享相同的硬件、存儲和網絡設備,並使用 Web 瀏覽器訪問服務和管理您的帳戶。公共雲部署經常用於提供基於 Web 的電子郵件、在線辦公應用程序、存儲以及測試和開發環境。

優勢:
降低成本——無需購買硬件或軟件,您只需為使用的服務付費。
無需維護——您的服務提供商提供維護。
近乎無限的可擴展性——按需資源可滿足您的業務需求。
高可靠性——龐大的服務器網絡確保不會出現故障。

私有云由一個企業或組織專門使用的雲計算資源組成。私有云可以物理地位於您組織的現場數據中心,也可以由第三方服務提供商託管。但在私有云中,服務和基礎設施始終在私有網絡上維護,硬件和軟件專門用於您的組織。

通過這種方式,私有云可以讓組織更輕鬆地自定義其資源以滿足特定的 IT 要求。私有云通常被政府機構、金融機構和任何其他具有關鍵業務運營的中大型組織所使用,這些組織尋求增強對環境的控制。

私有雲:

更大的靈活性——您的組織可以自定義其云環境以滿足特定的業務需求。
更多控制——資源不與他人共享,因此可以實現更高級別的控制和隱私。
更高的可擴展性——與本地基礎設施相比,私有云通常提供更高的可擴展性。

解答

答案是 C. 混合式雲端。

推薦資源

Microsoft AZ-900 Exam免費考古題

總結

AZ-900都是以簡單快速記憶為主,不需要深度記憶與推理,廣度大於深度,快速掃過的效益比才是最高的,時間不夠可以直接刷考古題,不建議找太舊的。

可參考當次的考試指南,這樣比較有方向,網路考古題有些答案是錯的,而且分歧極大,遇到這種題目都建議直接找官方文檔。

不過要是像我一樣前天晚上才準備了話建議是直接pass,還記得走出考場的時候只花了一半時間,壓線通過,監考官還疑惑地問說今天怎麼這麼多人都來考,完成後必須在登記表上
簽退,掃了一下當天大概有4個來考,並不是每一位都通過。

https://azure.microsoft.com/en-gb/resources/cloud-computing-dictionary/what-is-iaas/#faq

]]>
diff --git a/sitemap.xml b/sitemap.xml index 07ca9c69..3464acd6 100644 --- a/sitemap.xml +++ b/sitemap.xml @@ -1,6 +1,15 @@ + + https://www.boris.idv.tw/(%E9%81%8A%E6%88%B2)%E7%8D%A8%E8%87%AA%E6%AE%B2%E6%BB%8511%E5%90%8DPUBG%E7%8E%A9%E5%AE%B6%E4%B8%A6%E5%90%83%E9%9B%9E/ + + 2023-12-10 + + monthly + 0.6 + + https://www.boris.idv.tw/(%E6%8A%80%E8%A1%93)Laravel-Queue-%E8%A8%8A%E6%81%AF%E9%9A%8A%E5%88%97/ @@ -193,176 +202,176 @@ https://www.boris.idv.tw/ - 2023-11-19 + 2023-12-10 daily 1.0 - https://www.boris.idv.tw/tags/Diary/ - 2023-11-19 + https://www.boris.idv.tw/tags/Agile/ + 2023-12-10 weekly 0.2 - https://www.boris.idv.tw/tags/Agile/ - 2023-11-19 + https://www.boris.idv.tw/tags/Diary/ + 2023-12-10 weekly 0.2 - https://www.boris.idv.tw/tags/Queue/ - 2023-11-19 + https://www.boris.idv.tw/tags/AZ-900/ + 2023-12-10 weekly 0.2 - https://www.boris.idv.tw/tags/Swagger/ - 2023-11-19 + https://www.boris.idv.tw/tags/Frontend/ + 2023-12-10 weekly 0.2 - https://www.boris.idv.tw/tags/Linux/ - 2023-11-19 + https://www.boris.idv.tw/tags/Queue/ + 2023-12-10 weekly 0.2 - https://www.boris.idv.tw/tags/Lubuntu/ - 2023-11-19 + https://www.boris.idv.tw/tags/Linux/ + 2023-12-10 weekly 0.2 - https://www.boris.idv.tw/tags/AZ-900/ - 2023-11-19 + https://www.boris.idv.tw/tags/Lubuntu/ + 2023-12-10 weekly 0.2 - https://www.boris.idv.tw/tags/Frontend/ - 2023-11-19 + https://www.boris.idv.tw/tags/Swagger/ + 2023-12-10 weekly 0.2 https://www.boris.idv.tw/tags/Backend/ - 2023-11-19 + 2023-12-10 weekly 0.2 - https://www.boris.idv.tw/tags/LineBot/ - 2023-11-19 + https://www.boris.idv.tw/tags/Authentication/ + 2023-12-10 weekly 0.2 - https://www.boris.idv.tw/tags/Line-API/ - 2023-11-19 + https://www.boris.idv.tw/tags/Authorization/ + 2023-12-10 weekly 0.2 - https://www.boris.idv.tw/tags/Youbike-API/ - 2023-11-19 + https://www.boris.idv.tw/tags/Monica/ + 2023-12-10 weekly 0.2 - https://www.boris.idv.tw/tags/render/ - 2023-11-19 + https://www.boris.idv.tw/tags/Laravel/ + 2023-12-10 weekly 0.2 - https://www.boris.idv.tw/tags/Authentication/ - 2023-11-19 + https://www.boris.idv.tw/tags/OAuth/ + 2023-12-10 weekly 0.2 - https://www.boris.idv.tw/tags/Authorization/ - 2023-11-19 + https://www.boris.idv.tw/tags/RESTful-API/ + 2023-12-10 weekly 0.2 - https://www.boris.idv.tw/tags/RESTful-API/ - 2023-11-19 + https://www.boris.idv.tw/tags/JWT/ + 2023-12-10 weekly 0.2 - https://www.boris.idv.tw/tags/JWT/ - 2023-11-19 + https://www.boris.idv.tw/tags/Parcel/ + 2023-12-10 weekly 0.2 - https://www.boris.idv.tw/tags/Laravel/ - 2023-11-19 + https://www.boris.idv.tw/tags/LineBot/ + 2023-12-10 weekly 0.2 - https://www.boris.idv.tw/tags/Monica/ - 2023-11-19 + https://www.boris.idv.tw/tags/Line-API/ + 2023-12-10 weekly 0.2 - https://www.boris.idv.tw/tags/OAuth/ - 2023-11-19 + https://www.boris.idv.tw/tags/Youbike-API/ + 2023-12-10 weekly 0.2 - https://www.boris.idv.tw/tags/Parcel/ - 2023-11-19 + https://www.boris.idv.tw/tags/render/ + 2023-12-10 weekly 0.2 https://www.boris.idv.tw/tags/CI-CD/ - 2023-11-19 + 2023-12-10 weekly 0.2 https://www.boris.idv.tw/tags/Github-Action/ - 2023-11-19 + 2023-12-10 weekly 0.2 https://www.boris.idv.tw/tags/CICD-Pipeline/ - 2023-11-19 + 2023-12-10 weekly 0.2 @@ -371,42 +380,42 @@ https://www.boris.idv.tw/categories/Diary/ - 2023-11-19 + 2023-12-10 weekly 0.2 - https://www.boris.idv.tw/categories/Linux/ - 2023-11-19 + https://www.boris.idv.tw/categories/Frontend/ + 2023-12-10 weekly 0.2 - https://www.boris.idv.tw/categories/Frontend/ - 2023-11-19 + https://www.boris.idv.tw/categories/Linux/ + 2023-12-10 weekly 0.2 - https://www.boris.idv.tw/categories/Line-API/ - 2023-11-19 + https://www.boris.idv.tw/categories/Backend/ + 2023-12-10 weekly 0.2 - https://www.boris.idv.tw/categories/Backend/ - 2023-11-19 + https://www.boris.idv.tw/categories/Line-API/ + 2023-12-10 weekly 0.2 https://www.boris.idv.tw/categories/CI-CD/ - 2023-11-19 + 2023-12-10 weekly 0.2 diff --git a/tags/AZ-900/index.html b/tags/AZ-900/index.html index 0ff444c8..0efaae7e 100644 --- a/tags/AZ-900/index.html +++ b/tags/AZ-900/index.html @@ -38,7 +38,7 @@ toc: true, rightside: false, } -}
\ No newline at end of file + })(window)
\ No newline at end of file diff --git a/tags/Agile/index.html b/tags/Agile/index.html index 132798bc..aee4fa99 100644 --- a/tags/Agile/index.html +++ b/tags/Agile/index.html @@ -38,7 +38,7 @@ toc: true, rightside: false, } -}
\ No newline at end of file + })(window)
\ No newline at end of file diff --git a/tags/Authentication/index.html b/tags/Authentication/index.html index c508477b..104970e7 100644 --- a/tags/Authentication/index.html +++ b/tags/Authentication/index.html @@ -38,7 +38,7 @@ toc: true, rightside: false, } -}
\ No newline at end of file + })(window)
\ No newline at end of file diff --git a/tags/Authorization/index.html b/tags/Authorization/index.html index 230bd344..c29d7193 100644 --- a/tags/Authorization/index.html +++ b/tags/Authorization/index.html @@ -38,7 +38,7 @@ toc: true, rightside: false, } -}
\ No newline at end of file + })(window)
\ No newline at end of file diff --git a/tags/Backend/index.html b/tags/Backend/index.html index 1cee202a..c32c83ab 100644 --- a/tags/Backend/index.html +++ b/tags/Backend/index.html @@ -38,7 +38,7 @@ toc: true, rightside: false, } -}
\ No newline at end of file + })(window)
\ No newline at end of file diff --git a/tags/CI-CD/index.html b/tags/CI-CD/index.html index 78cacf65..8a92719d 100644 --- a/tags/CI-CD/index.html +++ b/tags/CI-CD/index.html @@ -38,7 +38,7 @@ toc: true, rightside: false, } -}
\ No newline at end of file + })(window)
\ No newline at end of file diff --git a/tags/CICD-Pipeline/index.html b/tags/CICD-Pipeline/index.html index b3a6efd7..02c68036 100644 --- a/tags/CICD-Pipeline/index.html +++ b/tags/CICD-Pipeline/index.html @@ -38,7 +38,7 @@ toc: true, rightside: false, } -}
\ No newline at end of file + })(window)
\ No newline at end of file diff --git a/tags/Diary/index.html b/tags/Diary/index.html index dc2b0fda..eff71651 100644 --- a/tags/Diary/index.html +++ b/tags/Diary/index.html @@ -38,7 +38,7 @@ toc: true, rightside: false, } -}
\ No newline at end of file + })(window)
\ No newline at end of file diff --git a/tags/Frontend/index.html b/tags/Frontend/index.html index 57e5c229..94719b27 100644 --- a/tags/Frontend/index.html +++ b/tags/Frontend/index.html @@ -38,7 +38,7 @@ toc: true, rightside: false, } -}
\ No newline at end of file + })(window)
\ No newline at end of file diff --git a/tags/Github-Action/index.html b/tags/Github-Action/index.html index 685f1a62..3b7c6770 100644 --- a/tags/Github-Action/index.html +++ b/tags/Github-Action/index.html @@ -38,7 +38,7 @@ toc: true, rightside: false, } -}
\ No newline at end of file + })(window)
\ No newline at end of file diff --git a/tags/JWT/index.html b/tags/JWT/index.html index 70abd190..d60645f0 100644 --- a/tags/JWT/index.html +++ b/tags/JWT/index.html @@ -38,7 +38,7 @@ toc: true, rightside: false, } -}
\ No newline at end of file + })(window)
\ No newline at end of file diff --git a/tags/Laravel/index.html b/tags/Laravel/index.html index a271dc36..a3a7499e 100644 --- a/tags/Laravel/index.html +++ b/tags/Laravel/index.html @@ -38,7 +38,7 @@ toc: true, rightside: false, } -}
\ No newline at end of file + })(window)
\ No newline at end of file diff --git a/tags/Line-API/index.html b/tags/Line-API/index.html index cf66b407..6f70cb65 100644 --- a/tags/Line-API/index.html +++ b/tags/Line-API/index.html @@ -38,7 +38,7 @@ toc: true, rightside: false, } -}
\ No newline at end of file + })(window)
\ No newline at end of file diff --git a/tags/LineBot/index.html b/tags/LineBot/index.html index bcd1d97f..d5e90086 100644 --- a/tags/LineBot/index.html +++ b/tags/LineBot/index.html @@ -38,7 +38,7 @@ toc: true, rightside: false, } -}
\ No newline at end of file + })(window)
\ No newline at end of file diff --git a/tags/Linux/index.html b/tags/Linux/index.html index 39e65e85..dfa4e7e9 100644 --- a/tags/Linux/index.html +++ b/tags/Linux/index.html @@ -38,7 +38,7 @@ toc: true, rightside: false, } -}
\ No newline at end of file + })(window)
\ No newline at end of file diff --git a/tags/Lubuntu/index.html b/tags/Lubuntu/index.html index 2c3e62f4..a66b3699 100644 --- a/tags/Lubuntu/index.html +++ b/tags/Lubuntu/index.html @@ -38,7 +38,7 @@ toc: true, rightside: false, } -}
\ No newline at end of file + })(window)
\ No newline at end of file diff --git a/tags/Monica/index.html b/tags/Monica/index.html index 3458e7e5..25e56a14 100644 --- a/tags/Monica/index.html +++ b/tags/Monica/index.html @@ -38,7 +38,7 @@ toc: true, rightside: false, } -}
\ No newline at end of file + })(window)
\ No newline at end of file diff --git a/tags/OAuth/index.html b/tags/OAuth/index.html index 888c0eb3..8614ca38 100644 --- a/tags/OAuth/index.html +++ b/tags/OAuth/index.html @@ -38,7 +38,7 @@ toc: true, rightside: false, } -}
\ No newline at end of file + })(window)
\ No newline at end of file diff --git a/tags/Parcel/index.html b/tags/Parcel/index.html index 0f05bba3..1144bc23 100644 --- a/tags/Parcel/index.html +++ b/tags/Parcel/index.html @@ -38,7 +38,7 @@ toc: true, rightside: false, } -}
\ No newline at end of file + })(window)
\ No newline at end of file diff --git a/tags/Queue/index.html b/tags/Queue/index.html index 45cc38da..0ec05a19 100644 --- a/tags/Queue/index.html +++ b/tags/Queue/index.html @@ -38,7 +38,7 @@ toc: true, rightside: false, } -}
\ No newline at end of file + })(window)
\ No newline at end of file diff --git a/tags/RESTful-API/index.html b/tags/RESTful-API/index.html index 573ed85e..c132bd1d 100644 --- a/tags/RESTful-API/index.html +++ b/tags/RESTful-API/index.html @@ -38,7 +38,7 @@ toc: true, rightside: false, } -}
\ No newline at end of file + })(window)
\ No newline at end of file diff --git a/tags/Swagger/index.html b/tags/Swagger/index.html index 218714bb..0d535b07 100644 --- a/tags/Swagger/index.html +++ b/tags/Swagger/index.html @@ -38,7 +38,7 @@ toc: true, rightside: false, } -}
\ No newline at end of file + })(window)
\ No newline at end of file diff --git a/tags/Youbike-API/index.html b/tags/Youbike-API/index.html index 6aca1bc9..23e437f7 100644 --- a/tags/Youbike-API/index.html +++ b/tags/Youbike-API/index.html @@ -38,7 +38,7 @@ toc: true, rightside: false, } -}
\ No newline at end of file + })(window)
\ No newline at end of file diff --git a/tags/index.html b/tags/index.html index 9d4a278a..0969260f 100644 --- a/tags/index.html +++ b/tags/index.html @@ -123,7 +123,7 @@ } } detectApple() - })(window)
\ No newline at end of file +}
\ No newline at end of file diff --git a/tags/render/index.html b/tags/render/index.html index 960bb02b..3e7ff237 100644 --- a/tags/render/index.html +++ b/tags/render/index.html @@ -38,7 +38,7 @@ toc: true, rightside: false, } -}
\ No newline at end of file + })(window)
\ No newline at end of file