標籤:

不花錢給女友過生日是一種怎樣的體驗?

今天是她的生日,也是我陪她度過的第一個生日,作為家庭地位不可撼動(墊底)的男人,為了維持寵愛,當然要為女神大人準備一份精心準備的禮物。在刷了幾天的淘寶天貓,在對比了禮物單價與平時消費,並且滿心歡喜地發現收藏夾和 <你收到男友送的最蠢的禮物是什麼?>高度重合後,我決定自己動手。如果你和我一樣有個程序媛妹子,渣 coding 還不想花錢,還想送點什麼不一樣的東西可以參照此篇教程送她一個驚喜(嚇)。

emmm. 筆者無法保證效果,畢竟我也拿不準一會會不會就此失寵。

此為背景。

---------------用電腦,先下再看,么么噠。---------------

<click here>.

---------------忐忑的分割線---------------

調研:<區塊鏈是什麼,如何簡單易懂地介紹區塊鏈?> 去中心化?不可篡改?新增共識?還是個鏈?不管你們拿區塊鏈去幹嘛反正我是用來表白了。

目標:代碼實現完整功能的區塊鏈,用合適的方式可視化。

創新:反正我沒見過有人這麼玩。

需要知識:python 基礎

實現:

1.python實現私有區塊鏈

1.1 主體

主體部分參考教程 <learn-blockchains-by-building-one>或譯文<用Python從零開始創建區塊鏈> 。整體並不複雜,跟著教程做就可以了,需要注意的是本地地址 Windows 要用127.0.0.1,Mac/Linux 0.0.0.0 別的沒什麼問題。

1.2 修改

為了體現給女朋友過生日和曬狗糧的核心思想,對原本的初始塊和工作量證明做了小的修改

1.2.1 創世塊

timestamp:修改為我們確認關係的時刻

proof: 修改為1314

previous_hash:修改為我們第一次見面的地點的 sha256 哈希值

代碼沒什麼好貼的,讀者看著改,都簡單。

1.2.2 工作量證明

如果時間不夠,可以按教程的簡單實現頭部4位的尋值,1314,0520,什麼的都隨意,此時的演算法複雜度可以保證短時間生成大量的塊不至於看著寒酸。為了體現鏈結構的愛情象徵意義,筆者對 POW 演算法做了如下修改:

return (guess_hash[:3] == self.u) & (guess_hash[-3:] == self.i)

哈希值頭部是女票名字的 ASCII 累加值,尾部是我的, 加上鏈式結構象徵手牽著手(嘿嘿嘿)。代碼同樣沒什麼好貼的,很簡單了。需要注意工作量證明使用的 POW 演算法複雜度和位數不是均勻變化,每添加一位時間增長十分恐怖,這裡用的是 6 位數的 POW 演算法,讀者應該避免過長的位數,不然挖不出來就很尷尬。

1.3 挖礦

這裡就很簡單,隨隨便便寫個腳本,用 requests 發送請求就好了。

import requestss = requests.session()while True: s.get(http://0.0.0.0:5000/mine)

找一台平時閑置的電腦,因為演算法不是很複雜,隨隨便便就能跑,慢點就慢點,設置的合理就不會尷尬到顆粒無收,當前的複雜度大概一分鐘能挖兩個,不過到後期時間應該會大幅增長,僅做參考。

1.4 XXCoin

按照虛擬貨幣約定俗成 XXCoin 的叫法,現在可以給你的禮物取一個女友的名字了。然後你會得到最終結果,一條充滿內涵的專屬區塊鏈:

這特么都是啥。。。搞笑呢么?因為需要導出這鏈還特么是斷的。。這特么能送出去么?

為了好歹像點樣子,進入下一章。

2.鏈展示

由於得到的是哈希值這樣完全無法可視化,就算勉強轉化也是一片白雜訊的東西 ,

"8829b8afce769a728a55a4c3199196e3c9661cbd4dfe2e065716f589ec06e6b0"

而且筆者此時寫文檔才發現精心準備的小彩蛋還忘記寫進塊里去了(摔)。

response = { message: "Love You ********** ", index: block[index], transactions: block[transactions], proof: block[proof], previous_hash: block[previous_hash], }

聯想到憧憬中的美好願望,針對展示問題採取以下方案。

  • 哈希值轉化地理坐標。
  • 用飛線圖鏈接城市坐標用於數據展示。

2.1 哈希值轉化地理坐標

根據坐標取值範圍,總可以找到一個轉換方式將哈希值轉化為坐標。但是由於 POW 演算法添加了限制,無法保證數據量小的情況下能達到足夠均勻,試想畫了 100 個點 88 個都在瑞士那麼大的地方怎麼畫都不會好看;而且由於地表上70%都是水,最後所有點都聚在太平洋上一個瑞士那麼大點的地方更是十分糟心- -。

為了避免上面尷尬局面,這裡採用以下處理方式。

  1. 獲取世界城市目錄和經緯度
  2. 已獲取的每個 Coin 上的哈希值轉化後作為 random seed,目錄中不放回抽樣一個城市
  3. 導出數據用於可視化

2.1.1 世界城市目錄及經緯度

數據是從某不存在的網站上找到的<Free World Cities Database>。

需要注意原始數據中存在一些奇怪的字元應該是別的語言,讀取數據會有字元編碼問題需要用 utf-8 重新編譯一下,另外每個城市分配了四個坐標可能表示合圍區域,沒測,用的時候直接拿的均值。代碼比較常規,使用 pandas 和 numpy 沒啥說的。

# -*- coding: utf-8 -*- #import pandas as pdimport numpy as npread_cities = pd.read_csv(worldcitiespop.txt, sep=",", usecols=[City,Latitude, Longitude])cities = pd.pivot_table(read_cities,index=City, aggfunc=mean)cities_index = np.arange(cities.shape[0])

2.1.2 城市抽樣

random seed 的位數一般有限制,哈希值那麼一大長串又是很煩,這裡做了下面的處理,

for i in coins_hash: seed = sum([ord(j) for j in i])

seed 值等於哈希值每一位的 ASCII 碼 數字加和,這要是還重了就也很無奈…

這裡的處理有一個技巧,沒必要在城市列表這種字元串表上進行抽樣,而且也沒必要每個循環都把數據抽出來。可以利用循環構造一個亂序的索引,然後帶回到原數據表就可以了。

read_coins = pd.read_json(chain.json)coins = read_coins.chain.valuescoins_hash = np.array([i[previous_hash] for i in coins])cities_index = np.arange(cities.shape[0])first_city = np.where(cities.index.values == beijing)[0][0]cities_list = [first_city] # our first date !for i in coins_hash: seed = sum([ord(j) for j in i]) np.random.seed(seed) city_index = np.random.choice(cities_index, 1)[0] cities_index = np.delete(cities_index, city_index) cities_list.append(city_index)world = pd.DataFrame(cities.iloc[cities_list])

2.1.3 數據導出

不涉及前端的情況下就離線存成 csv 就行,沒啥好說的。

world.to_csv(world.csv)

此時得到了這樣的東西,嗯..可以用了。

這裡其實有比單純的用 seed 更好的方式,比如哈希串對拆之後 ASCII 轉換成數字, 整體均一化之後縮放到坐標的數值範圍,然後用 KNN 使 k=1 找到該點最近的城市。麻煩的地方在於為了保證點足夠均勻轉換要廢些功夫,為女友準備個生日禮物而已,犯不著花心思(記得劃掉)。

2.2 飛線圖

飛線圖就是這玩意,上圖表示全球航班的航線,很像鏈有木有,我盯上這個可視化很久了!可惜臨到使用的時候發現:

摔!

這個時候換方案已經晚(懶得想新的)了,最終方案只能用 tableau 畫個靜態的了...

由於 tableau 這玩意沒用過,稍微研究了下,具體實現:

2.2.1 載入數據源,沒啥說的

2.2.2 載入地圖

標記中選地圖-經緯度數據拖到相應位置,沒啥說的。

2.2.3 連線

標記選連線 City 拖進去,為了體現鏈接順序,order 拖到路徑,沒啥好說的。

2.2.4 美化

就隨便改改就行,然後你會得到:

這就是結果了。。。

這特么啥呀。。。一點也不好看,看著就是個 random 出來的破圖好嗎。。。摔!

為了稍微體現點工作量,進入下一章。

3.湊工作量

圖都做了不能白做是不是~為了更好地完善一起旅行的美好願望對原方案添加了一些畫蛇添足的東西。

3.1 獲取國家名

在源坐標數據里做了些修改,cities 的基礎上又統計了國家代碼。通過 pycountry 包轉化成國家名稱,最後按原哈希 seed 的生成順序輸出。

代碼寫的比較省事,看不懂的同學耐心拆一下,畢竟給女朋友寫的而已,用不著什麼可讀性。

import pycountry...countries = read_cities.iloc[cities_list, 0].apply(lambda x: pycountry.countries.get(alpha_2=x.upper()).name)countries = countries.drop_duplicates()countries.to_csv(./output/countries.csv, index=False)

3.2 收集圖片

根據國家名稱搜集好看的圖片,由於之前轉化的都是英文國家名,因為懶得找匹配表所以直接外網搜了,通常谷歌就夠,這裡我用的 <pinterest.com/>,圖片會好看一點。

本來按照上面的行文風格,此處應該有爬蟲,但是我試了下實在是爬出來的圖片參差不齊根本沒法用,為了避免挨揍,這裡肉手每個國家篩了幾張比較好看的。為了尊重版權,希望後來者自己用用就好不要商用。

3.3 前端頁面

原料齊了,因為這堆東西太零散,於是隨便寫了個前端頁面,因為太丑了也不太好意思教,自己看代碼吧。

所以...這個就是完成品了,一個完全沒價值又非常耗費時間的東西…@xiaoyusilen

<想要和你手拉手,走過全世界>.


小公主,陪你過的第一個生日,生日快樂。

ps: coding 和 data 部分後續共享在 github 。


推薦閱讀:

為什麼女生都想找個程序猿男朋友,而程序猿都說找不到女朋友?
男生太瘦了被對象嫌棄,怎麼辦?
月經量減少是怎麼回事?周期穩定 也不痛經 就是量極其少?
我今年21,比較早熟,我女朋友比我大六歲,我個人比較隨性,而且話很少,她現在覺得我和她有代溝,不解!?
許嵩有沒有女朋友?

TAG:女朋友 |