這個作業屬於哪個課程 | https://edu.cnblogs.com/campus/fzu/SE2020 |
---|---|
這個作業要求在哪里 | https://edu.cnblogs.com/campus/fzu/SE2020/homework/11167 |
這個作業的目標 | 制作一個程序統計和分析 GitHub 的用戶行為數據。 |
學號 | 031802542 |
PSP2.1 | Personal Software Process Stages | 預估耗時(分鍾) | 實際耗時(分鍾) |
---|---|---|---|
Planning | 計划 | 30 | 90 |
Estimate | 估計這個任務需要多少時間 | 10 | 10 |
Development | 開發 | 120 | 120 |
Analysis | 需求分析 (包括學習新技術) | 180+ | 360 |
Design Spec | 生成設計文檔 | 30 | 0 |
Design Review | 設計復審 | 10 | 0 |
Coding Standard | 代碼規范 (為目前的開發制定合適的規范) | 30 | 60 |
Design | 具體設計 | 0 | 0 |
Coding | 具體編碼 | 0 | 0 |
Code Review | 代碼復審 | 20 | 0 |
Test | 測試(自我測試,修改代碼,提交修改) | 30 | 10 |
Reporting | 報告 | 30 | 60 |
Test Report | 測試報告 | 10 | 0 |
Size Measurement | 計算工作量 | 10 | 0 |
Postmortem & Process Improvement Plan | 事后總結, 並提出過程改進計划 | 30 | 20 |
合計 | 540+ | 705 |
至2020.9.13
花了40分鍾多時間學習了Github的使用,雖然依舊是雲里霧里但好歹勉強會用了。同時花了20分鍾左右看了代碼規范。
看了樣例數據發現是json文件格式同時對格式一無所知完全不知道怎么處理,詢問了學長這類作業的捷徑,被推薦使用pythonpython大法平安保。
2020.9.14
學長:“我曾經花了一天就學完了python。”
晚上花了2個小時多查找了有關python導入json文件的資料,以及自己再反復琢磨,大概有了以下代碼:
import json
#實現讀入json文件並且輸出每個事件的類型
file = open('inputfile.json', 'r', encoding='utf-8')
for x in file:
y = json.loads(x)
print(y['type'])
目前對於json文件格式大致有個了解了。需要的有事件類型、用戶和對應項目,目前找到了事件類型和用戶(id)但找不到項目對應名字的位置。
以及對格式要求的一些交互操作完全沒有了解,同時對本身python也比較陌生,還有如何存儲大數據的問題。
預計明天解決:在小數據規模的情況下,統計每個人4種事件個數。
2020.9.15
稍微花了1小時整理了一下思緒:
初始化:讀入文件夾,訪問文件夾里的所有json文件並將數據進行處理
數據處理方法:
1.定義類pers,包含四種event的個數,表示一個用戶的四種事件分別的個數
2.定義類proj,包含不定個pers類,表示一個項目由不定數量的用戶管理(項目的事件個數由各個用戶的事件個數統計)
3.讀入處理的流程圖如下:
4.對於詢問的處理:
(1)如果是查詢用戶的事件個數,直接在用戶集合里查找
(2)如果是查詢某項目的事件個數,查找該項目並遍歷項目中的所有用戶的該事件,值相加得到結果
(3)如果是查詢用戶在某個項目中的事件個數,查找該項目並查找用戶的該事件
還花了大概不到1小時時間讀了讀示例代碼和目前已經提交過的同學的作業的代碼拓寬思路,但感覺思路有點被帶偏了所以最后還是打算大體上按自己的想法寫(可能有些細節會去參考,比如指令設置)。
又花了3個多小時百度以及亂搞學習,熟悉了python的最基礎的使用,進度上已經能將基礎的數據處理轉移進類里了:
import json
def trans(x):
#將事件轉化成對應標號,-1表示不合法事件
if x == 'PushEvent':
return 0
if x == 'IssueCommentEvent':
return 1
if x == 'IssuesEvent':
return 2
if x == 'PullRequestEvent':
return 3
return -1
class Person():
def __init__(self,name):
self.name = name
self.evecnt = [0,0,0,0]
def addeve(self,event):
#添加事件
++ self.evecnt[trans(event)]
class Project():
def __init__(self,name):
self.name = name
self.group = list()
def addeve(self,pers,event):
#添加事件(如果用戶不在項目中則將用戶加入項目中)
Flag = 0
for i in self.group:
if group[i].name == pers.name:
++ group[i].evecnt[event]
Flag = 1
break
if Flag == 0:
temp = Person(tmp.name)
temp.addeve(event)
self.group.append(temp)
allPerson = list()
allProject = list()
file = open('inputfile.json', 'r', encoding='utf-8')
for i in file:
y = json.loads(i)
evetype=trans(y['type'])
if not evetype == -1:
tmp = Person(y['actor']['id'])
tmp.addeve(y['type'])
#添加用戶
Flag=0
for j in allPerson:
if j.name == tmp.name:
j.addeve(evetype)
Flag=1
break
if Flag == 0:
allPerson.append(tmp)
#添加項目
projName = y['repo']['id']
Flag=0
for j in allProject:
if j.name == projName:
j.addeve(tmp,evetype)
Flag=1
break
if Flag == 0:
temp = Project(projName)
temp.addeve(tmp,evetype)
allProject.append(temp)
#測試輸出所有用戶和項目
for i in allPerson:
print(i.name)
print("**")
for i in allProject:
print(i.name)
print(":")
for j in i.group:
print(j.name)
print("--")
雖然今天還完成不了統計但感覺快了(主要是明天時間多)。
2020.9.16
下午花了大概1個多小時看了看其他目前已經提交過博客的同學的代碼和樣例代碼,看不懂的百度,雖然還是有點雲里霧里,但可以肯定的一點就是數據量大到需要把輸入的數據處理完輸出,之后詢問再訪問處理過的數據。由於之前存儲方式是需要將輸入數據不斷比對,視情況加入,數據量大到沒法一次全部輸出,比對過程不斷訪問輸出文件也是很麻煩的事情,所以之前的設計全部都得否決。
那能想到的優化辦法就只有去除輸入的冗余信息然后輸出,之后查詢的時候遍歷輸出信息。
又花了大概3個小時以上(其實已經有點無法估計了)的時間了解參數指令以及文件的輸入輸出相關內容,但由於快到ddl了所以沒法很系統的學,大多數都是在復制粘貼。感謝丘總的幫助,我參考了她的博客,她也非常及時回答了我私聊的問題,當然也很感謝在群里幫忙解答的以及已經提交了作業的各個同學,你們的群里問答和博客都給我帶來了不少收獲。
那么先從最頭疼的如何解決輸入開始說起:
#指令參數初始化
def __init__(self):
self.parser = argparse.ArgumentParser()
self.data = None
self.argInit()
print(self.analyse())#開始調用指令
#指令參數添加
def argInit(self):
self.parser.add_argument('-i', '--init')
self.parser.add_argument('-u', '--user')
self.parser.add_argument('-r', '--repo')
self.parser.add_argument('-e', '--event')
看了很多人的寫法看的腦闊有點疼,最后發現還是樣例寫的比較簡潔(實際上是網上的代碼也差不多,但是要一點點復制下來改,所以懶得整了)。
這樣一來之后就可以用 parser.parse_args() 的這幾個參數了(格式如下):
#初始化
if self.parser.parse_args().init:
#init返回的是輸入數據文件夾位置
read(self.parser.parse_args().init)
return 0
else:
#訪問已處理數據
if self.data is None:
self.data = open('data.json', 'r', encoding = 'utf-8')
return solve(self.data,
self.parser.parse_args().user,
self.parser.parse_args().repo,
self.parser.parse_args().event)
處理輸入數據(文件搜索也是參考樣例寫的光速跑):
def read(path):
#初始化data文件以防重復寫入
with open('data.json', "w", encoding='utf-8') as f2:
f2.write('')
#搜索path路徑下的所有json文件
for root, dic, files in os.walk(path):
for file in files:
if file[-5:] == '.json':
json_path = file
filedir = open(path + '\\' + json_path, 'r', encoding='utf-8')
with open(json_path, encoding = 'utf-8') as f:
for i in f:
y = json.loads(i)
evetype = trans(y['type'])
#如果事件合法,將事件需要的信息提取出來寫入data文件
if not evetype == -1:
#提取關鍵數據到dict1
dict1 = {}
dict1['event'] = evetype
dict1['user'] = y['actor']['login']
dict1['repo'] = y['repo']['name']
#再把dict1輸出到data
dict2 = json.dumps(dict1)
with open('data.json', "a", encoding='utf-8') as f2:
f2.write(str(dict2) + '\n')
對於每個詢問的解決方法(因為看過丘總的解法印象很深所以寫的時候完全被她的思路帶跑了):
def solve(data, user, repo, event):
ans = 0
for i in data:
y = json.loads(i)
if not len(user) == 0:
if not user == y['user']:
continue
else:
pass
else:
pass
if not repo == None:
if not repo == y['repo']:
continue
else:
pass
if trans(event) == y['event']:
ans = ans + 1
else:
pass
return ans
單純拿了幾行數據試手,至少目前還沒發現什么問題(這個是已經初始化之后輸入的結果):
今天主要解決了代碼的核心問題——小規模數據能正確運行,(如果明天還沒截止的話)明天解決Github相關工作以及性能測試。
2020.9.17
今天是真的沒空了所以只做了Github的提交(而且提交的很不像樣):
還是做的太倉促了,以后得好好規划一下時間,不能最后幾天趕工。