目錄css
組員 | 職責 |
---|---|
緒佩 | 組織分工、改進前端、後端、雲化 |
莊卉 | 改進前端、後端 |
家偉 | 算法關鍵詞識別、附加題實現 |
家燦 | 數據庫 |
一好 | 算法隨機數、算法審查 |
鴻傑 | 算法隨機數、算法審查 |
政演 | 提供算法思路、附加題idea思路、博客撰寫 |
凱琳 | 前端審查 |
丹丹 | 前端審查 |
青元 | 前端改進 |
宇恆 | 前端審查 |
github地址html
運行結果前端
抽獎結果名單java
環境 | 名稱 |
---|---|
操做系統 | Windows10 |
編譯器 | Eclipse javaee |
本地服務器 | Tomcat |
數據庫 | MySQL |
可視化數據庫工具 | Navicat |
進入界面
c++
抽獎規則設定1
git
抽獎規則設定2
github
抽獎結果名單
web
錯誤提示
算法
發佈成功顯示
數據庫
本算法具備如下模式:
視頻連接:https://v.youku.com/v_show/id_XMzkyODA4NDY0OA==.html?spm=a2h0k.11417342.soresults.dtitle
隨機算法:
咱們的抽獎算法基於LCG算法,LCG(linear congruential generator)線性同餘算法,是一個古老的產生隨機數的算法。
本算法有如下優勢:
本算法基於的LCG算法由如下參數組成:
參數 | m | a | c | X |
---|---|---|---|---|
性質 | 模數 | 乘數 | 加數 | 隨機數 |
做用 | 取模 | 移位 | 偏移 | 做爲結果 |
LCG算法是以下的一個遞推公式,每下一個隨機數是當前隨機數向左移動 log2 a 位,加上一個 c,最後對 m 取餘,使隨機數限制在 0 ~ m-1 內
從該式能夠看出,該算法因爲構成簡單,具備如下優勢:
如下是針對不一樣參數 lcg 產生隨機數的效果圖
能夠看出,針對不一樣的參數,lcg產生的效果差異很大
如下是針對不一樣環境下的參數選擇
根據咱們機器的狀況,咱們選擇使用參數:
抽獎算法對兩種狀況進行了處理:
無發言剔除:當用戶只轉發抽獎關鍵字,而沒有相關發言時,直接剔出抽獎名單。
惡意刷屏:抽獎者能夠自行定義一個抽獎閾值φ1,當發言數超過φ1時,對該用戶進行中獎機率降權處理。
灌水剔除:抽獎者能夠自行定義一個抽獎閾值φ2,發送的表情數超過閾值的時候,斷定爲灌水,剔出抽獎名單
for (Map.Entry<String, Integer> en : map.entrySet()) { //System.out.println(en.getKey() + "=" + en.getValue()); x[i] = ( a * x[i-1] + b ) % m; if (en.getValue() < 0) { //發言爲空,剔出抽獎名單 i++; continue; } else if (en.getValue() > 0) { //惡意刷屏,下降權重 weight = en.getValue(); if (weight > 30) { weight = 30; } x[i] = (int) (x[i] * ((double)(30 - weight) / 30.0)); } map.put(en.getKey(), x[i]); //System.out.println(en.getKey() + "=" + en.getValue()); i++; }
紅黑樹是一種自平衡的二叉查找樹,是一種高效的查找樹。
提供良好的效率:可在O(logN)時間內完成查找、增長、刪除等操做,能保證在最壞狀況下,基本的動態幾何操做的時間均爲O(lgn)。只要求部分地達到平衡要求,下降了對旋轉的要求,任何不平衡都會在三次旋轉以內解決,從而提升了效率。抽獎伏安法涉及大量增刪改查操做,紅黑樹算法提供了良好的效率支撐。
提供性能下限保證:相比於BST,紅黑樹能夠能確保樹的最長路徑不大於兩倍的最短路徑的長度,可見其查找效果的最低保證。最壞的狀況下也能夠保證O(logN)的複雜度,好於二叉查找樹O(N)複雜度。在大數據量狀況下,紅黑樹算法爲抽獎算法提供良好的性能保證。
提供詞頻統計的高性能:紅黑樹的算法時間複雜度和AVL樹相同,但統計性能更高。插入 AVL樹和紅黑樹的速度取決於所插入的數據。在數據比較雜亂的狀況,則紅黑樹的統計性能優於AVL樹。在抽獎時時,數據分佈較爲雜亂,在此應用場景下,紅黑樹算法與抽獎器契合。
提供較小的資源開銷:與基於哈希的算法相比,基於紅黑樹方法帶來更小的資源開銷,程序消耗內存較少。哈希的算法佔用大量資源,須要維護大量的計數器,而且在哈希過程當中消耗了大量的計算資源。抽獎系統器消耗的資源較少。
現抽獎的人數也愈來愈多。例如:王思聰抽獎微博總數達到了六千萬對每一個抽獎帳號還須要維護巨大的數據量。惡意灌水、轉發的帳號,或是機器人帳號,將大大影響抽獎的性能。抽獎機器人大量的抽獎參與,也將給系統帶來很大的影響。對此,咱們設置了一個針對抽獎的惡意檢測功能。能夠針對灌水言論,設定一個閾值,能夠對閾值進行調整。當發言數超過閾值時,報出該爲惡意用戶,能夠列入黑名單。在以後的抽獎活動中,能夠屏蔽黑名單中的用戶,減小系統的資源消耗,同時保證公平性。該功能基於下文中基於sketch的數據處理功能,在較小的空間開銷下,完成數據挖掘。
而且,該功能能夠鼓勵有意義的發言,減小惡意灌水等不良行爲。
若是除去關鍵字後發送內容爲空斷定爲符合普經過濾規則,將除抽獎關鍵字外僅發送表情定義爲惡意灌水,標記爲num = 1,若是該id未出現過,存入map
private void handleMap(String talkContent) { boolean flag = true; int num = 0; if (filterType != 1) { talkContent = talkContent.replaceAll("#(.*)#", " "); //talkContent.replaceAll("、", " "); if (Pattern.matches("\\s*", talkContent)) { // 若是除去關鍵字後發送內容爲空-->符合普經過濾規則 flag = false; /*將除抽獎關鍵字外僅發送表情定義爲惡意灌水,標記爲num = 1*/ } else if (Pattern.matches("\\s*[\\[表情\\]]+\\s*", talkContent) && filterType == 3) { //System.out.println(talkContent); num = 1; } } if (!map.containsKey(userID) && flag) { // 若是該id未出現過 map.put(userID, num); // 存入map } else if (num > 0) { num = (int) map.get(userID) + 1; map.put(userID, num); } }
發言爲空,剔出抽獎名單,惡意刷屏,下降權重,加入惡意灌水名單,由於文本中聊天樣本數據過少,一次灌水即踢出名單,如下是文本數據大時考慮修改,少許刷屏僅下降權重
if (en.getValue() < 0) { //發言爲空,剔出抽獎名單 i++; continue; } else if (en.getValue() > 0) { //惡意刷屏,下降權重 weight = en.getValue(); if (weight > 0) { /*加入惡意灌水名單*/ //由於文本中聊天樣本數據過少,一次灌水即踢出名單 if (!uselessName.contains(en.getKey())) { uselessName.add(en.getKey()); x[i] = -1; continue; } //如下是文本數據大時考慮修改,少許刷屏僅下降權重 if (weight > 30) { weight = 30; } } x[i] = (int) (x[i] * ((double)(30 - weight) / 30.0)); }
實現效果
此處僅僅對該功能進行測試,因爲樣本數據不足,設定的閾值也較小,將黑名單的內容輸出到文件中能夠顯示以下內容:
咱們將該系統實如今雲端虛擬化設備上。用戶能夠在不一樣設備上調用該功能,便於產品的推廣使用和推廣。並且,人們經常忽略的是本地服務器的安全問題。本地服務器一般資源較少,安全機制不完善,一旦受到DDos攻擊,功能將癱瘓。而在雲端,有運營商提供良好的安全服務體系,大大提升安全性,保證系統可以正常運行。
咱們作了如下部署工做:
將雲端環境鏡像與本地環境匹配正確
雲端數據庫進行同步
將項目文件壓縮成wra形式傳至雲端
以上工做均正常操做完成
仍存在如下不足
瀏覽器沒法正常編譯jsp中嵌入的java代碼,致使和數據庫交互沒法實現,頁面之間跳轉出現bug。
雲端連接(仍在優化中):http://119.29.249.194/index.jsp
目前狀況:
本功能利用了Sketch對抽獎數據進行挖掘,能夠保持在高速條件下對海量數據的快速處理,節省空間資源。
現抽獎的活動越多,參與抽獎的人數也愈來愈多。例如:王思聰抽獎微博的轉發量、評論數、點贊數均達到了兩千萬,總數達到了六千萬,對每一個抽獎帳號還須要維護巨大的數據量。當須要對該數據進行處理挖掘的時候,巨大的數據量將消耗巨大的空間和計算資源。然而,咱們有時候只須要部分的數據信息,例如:想了解每一個地區用戶的發言數,咱們並不須要記下每個用的發言數量,並將它們累加起來,在容許的偏差範圍內,只須要了解這個數量的近似值便可。對此,咱們的算法基於Sketch的算法,將巨大的數據散列到Skecth內,在有限的空間內完成巨大的數據計算,減小資源開銷。
sketch 是一種基於散列的數據結構,能夠對海量數據,實時地存儲數據特徵信息,只佔用較小的空間資源,而且具有在理論上可證實的估計精度與內存的平衡特性。
Sketch的原理
sketch是基於散列的數據結構,經過設置散列函數,將具備相同散列值的鍵值數據存入相同的桶內,以減小空間開銷。桶內的數據值做爲測量結果,是真實值的近似。利用開闢二維地址空間,多重散列等技術減小散列衝突,提升測量結果的準確度。Count-Min 是一種典型的 sketch ,在 2004 年被提出。
實際上 Count-Min sketch 用到的是分類的思想:將具備相同哈希值的key歸爲一類,並使用同一個計數器計數。
當數據到來時,逐個記錄全部數據的信息,會帶來巨大的計算和空間資源開銷。而咱們的功能每每也無需記錄全部的信息。
基於CM-Sketch實現
Count-Min sketch由多個哈希函數(f1……fn)和一張二維表組成。二維表的每一個存儲空間維護了一個計數器,其中每一個哈希函數分別對應表中的每一行。當數據到來時,須要通過每一個哈希函數 f1……fn 的處理,根據處理獲得的哈希值分別存入每一行對應哈希值的計數器。有幾個哈希函數,就要計算幾回。算完後,取這m個計數器中的最小值,做爲計算的最終值。
設計考量
測量值偏大:使用哈希的方法會產生衝突,多個數據哈希到同一個桶內,那麼這個桶的計數值就會偏大。
爲何容許有偏差:在大量數據條件下,若把全部信息都準確地記錄下來,要消耗大量計算和空間開銷,沒法知足實時性;並且在不少狀況下,並不須要很是精確的數據,在必定程度上可靠的估計值,便足以知足需求。
爲何要設置多個哈希函數:若是隻設置一個哈希函數,多個流數據存入同一個桶,偏差就會很大。經過設計多個哈希函數,減小哈希值的衝突,以減小偏差。每一個流都要通過全部哈希函數的處理,存入不一樣的計數器中。計數器的最小值雖然仍是大於等於真實值,但最接近真實值。這也是 「 Count-Min 」的由來。
哈希函數個數:哈希函數越多,衝突越少,測量值越精確,但計算開銷大。須要權衡測量精度和準確度,來設置合適的哈希函數個數。
使用Sketch的方法,對數據進行處理,對文本數據進行處理後,設置好參數,使用多個散列函數對數據進行處理,將數據的出現次數存入桶內。以此咱們的算法基於Sketch的算法,將巨大的數據散列到Skecth內,在有限的空間內完成巨大的數據計算,減小資源開銷。
經過輸入eps和gamma值,能夠根據本身的系統環境調整資源開銷。因爲估計該測試環境的資源開銷大小,須要具有良好的數學知識,而且對個方面數據進行評估計算。咱們將空間開銷抽象封裝成錯誤估計值和精確度。只須要對本身的需求估計,肯定該參數值,就能夠知足對空間開銷的肯定。
如下是處理抽獎數據的類的定義:
public class CountMinSketch { private static final long LONG_PRIME = 4294967311l; private int width; private int depth; /** * eps(for error), 0.01 < eps < 1 the smaller the berrer */ private double eps; /** * gammga(probability for accuracy), 0 < gamma < 1 the bigger the better */ private double gamma; /** * used in generation of hash funtion */ private int aj; private int bj; private int total; /** * array of arrays of counters */ //private HashMap<String, Integer> C = new HashMap<>(); private int[][] C; private int[][] C2; /** * array of hash values for particular item contians two element arrays {aj, * bj} */ private int[][] hashes; public CountMinSketch(double eps, double gamma) { this.eps = eps; this.gamma = gamma; width = (int) Math.ceil(Math.exp(1.00) / eps); depth = (int) Math.ceil(Math.log(1.00 / gamma)); total = 0; C = new int[depth][width]; C2 = new int[depth][width]; initHashes(); }
其中,如下部分完成了調整兩個參數值對空間資源和計算準確度的權衡:
/** * eps(for error), 0.01 < eps < 1 the smaller the berrer */ private double eps; /** * gammga(probability for accuracy), 0 < gamma < 1 the bigger the better */ private double gamma; width = (int) Math.ceil(Math.exp(1.00) / eps); depth = (int) Math.ceil(Math.log(1.00 / gamma));
以上是算法得出的效果截圖,兩張圖的結果幾乎相同,少數數據略有不一樣,完成的功能的實現,達到預期效果,驗證了該近似算法。
困難:
解決辦法
困難:alpha還在單機階段課堂實戰已經進入web,時間分配不均,分工出現混亂,做爲後端負責人沒有檢查環境軟件版本甚至很多人沒有某某軟件,致使不熟悉。
解決辦法:冷靜冷靜冷靜,儘可能不焦慮,事情一件一件來(嗯,體會到了瀕臨死亡的感受)
困難:時間過短,對代碼要求很高,不容許迭代修改bug。算法全新,須要構思。附加題構思。
解決辦法:考慮到前一段學習的djb2散列函數,修改使用LCG線性同餘法,解決隨機數的問題。考慮在實際場景下,微博轉發數量太大,要進行數據挖掘等工做,須要耗費很大計算和空間資源,故使用LCG和Sketch解決。
困難:隨機數生成算法須要從網上查閱不少相關資料,須要同後端使用相同的類和傳參方式
困難:
1.編碼方面,在其餘人面前,真的是有點過於弱。
2.前端方面,淺顯的還能寫出來,深度一點的就會一直出bug。
3.擅長的東西過於單一,理解的知識也是過於膚淺,我的能力有待提高。
解決辦法:
1.看教程,一步步來。
2.看隊友操做,積累經驗。
解決辦法:在網上查找代碼,並同其餘同窗交流,制定相同的傳參規則
困難:前端界面太不友好,不瞭解代碼,修改起來有難度。與後端交接時,返回值有待商榷。
解決辦法:查看網上代碼,下載模板進行修改。
困難:
解決辦法:
困難:
解決辦法
困難:對於抽獎應該如何實現沒有頭緒
解決辦法:求助了組內的周政演和黃鴻傑同窗
困難:
解決辦法:
困難:對於web很麼有經驗,對於排版,真的難爲我這個男生
解決辦法:找了一個婚慶的模板套了一下,改了些字和圖
因爲本次現場編程開發進度低於預期,給每位同窗一個一句話吐槽機會,格式爲:若是……,那麼……
若是能睡一個好覺,那麼我會補一個月的覺
若是我有好好學搜索引擎或者好好看前端,那麼此次做業你們作起來都會快不少
若是時間長一點,那麼我還有不少idea能夠實現呢
若是我能力強一些,那麼個人團隊就能夠更快更完美的完成這項項目。
若是給定時間長一點或者不在考試以前發佈這麼複雜的問題,那麼你們能更輕鬆愉快地完成這項任務。
若是能拿到相關教程,學習一段時間,那麼咱們就不會感受很慌張
若是能重來,那麼我必定要在課前學習,課上裝逼。
若是能重來一次,那麼我可能會選擇作自閉軟件或者直接自閉吧
若是我再強一些,那麼個人團隊就能夠更開心的完成
若是能重來一次,,那麼你們能更輕鬆愉快地完成這項任務。
若是我再強一些,那麼咱們就不會感受很慌張
隊員名 | 貢獻度 |
---|---|
胡緒佩 | 15% |
周政演 | 11.5% |
黃鴻傑 | 8% |
葛家燦 | 9% |
何宇恆 | 4% |
胡青元 | 11.5% |
劉一好 | 4% |
劉愷琳 | 4% |
翟丹丹 | 6% |
何家偉 | 12% |
莊卉 | 15% |
PSP2.1 | header 2 | 預估耗時(分鐘) | 實際耗時(分鐘) |
---|---|---|---|
Planning | 計劃 | 40 | 30 |
· Estimate | ·估計這個任務須要多少時間 | 20 | 20 |
Development | 開發 | 150 | 240 |
· Analysis | 需求分析(包括學習新技術) | 10 | 120 |
· Design Spec | · 生成設計文檔 | 0 | 0 |
· Design Review | · 設計複審 | 0 | 0 |
· Coding Standard | · 代碼規範 (爲目前的開發制定合適的規範) | 0 | 0 |
· Design | · 具體設計 | 180 | 150 |
· Coding | · 具體編碼 | 120 | 600 |
· Code Review | · 代碼複審 | 30 | 120 |
· Test | ·測試(自我測試,修改代碼,提交修改) | 100 | 100 |
Reporting | 報告 | 10 | 10 |
· Test Repor | · 測試報告 | 0 | 0 |
· Size Measurement | · 計算工做量 | 0 | 0 |
· Postmortem & Process Improvement Plan | · 過後總結, 並提出過程改進計劃 | 20 | 20 |
合計 | 680 | 1410 |
第N周 | 新增代碼(行) | 累計代碼(行) | 本週學習耗時(小時) | 累計學習耗時(小時) | 重要成長 |
---|---|---|---|---|---|
1 | 391 | 391 | 25 | 25 | 複習c++,學習單元測試和代碼覆蓋率,更熟悉Visual Studio的使用 |
2 | 100 | 491 | 5 | 30 | 在優化代碼和改bug |
3 | 0 | 0 | 15 | 45 | 閱讀《構建之法》第三章和第八章,學習使用Axure RP8,對UI設計有進一步瞭解和認識,對項目開發架構進一步的理解 |
4 | 441 | 932 | 25 | 70 | 對爬蟲初步認識,還有待學習(隊友負責模塊),Debug能力++; |
5 | 0 | 932 | 15 | 85 | 詳細瞭解需求規格說明書以及接口文檔書寫 |
6 | 232 | 1164 | 20 | 105 | 學習基礎前端界面佈局及學習思惟導圖製做 |
7 | 597 | 1761 | 20 | 125 | 學習前端交互,查資料能力++,對前端認識愈來愈深,恐懼愈來愈大,懂得作一個項目的艱難! |