第一次软件工程编程作业

这个作业属于哪个课程 https://edu.cnblogs.com/campus/fzu/SE2020
这个作业要求在哪里 https://edu.cnblogs.com/campus/fzu/SE2020/homework/11167
这个作业的目标 <制作一个程序统计和分析 GitHub 的用户行为数据。>
学号 <031802537>

一、PSP表格

PSP2.1 Personal Software Process Stages 预估耗时(分钟) 实际耗时(分钟)
Planning 计划 60
Estimate 估计这个任务需要多少时间 10
Development 开发 180
Analysis 需求分析 (包括学习新技术) 240
Design Spec 生成设计文档 60
Design Review 设计复审 30
Coding Standard 代码规范 (为目前的开发制定合适的规范) 60
Design 具体设计 60
Coding 具体编码 60
Code Review 代码复审 30
Test 测试(自我测试,修改代码,提交修改) 30
Reporting 报告 60
Test Report 测试报告 60
Size Measurement 计算工作量 10
Postmortem & Process Improvement Plan 事后总结, 并提出过程改进计划 30
合计 980

二、前言

第一次浏览完这次作业的时候是懵逼的,原来一个只会c/c++/一丢丢python的小白竟然可以一步登天成长为一个大佬,也可以一周搞定这种完全看不懂的作业吗。然后开始搜这几种信息类型的名字————果然什么也没搜到。。尝试跑一下学长给的测试代码,果然报错了。。只好向有开发经验的大佬和舍友请教,自己再一点一点慢慢学,以下是一些学习过程和网址。
首先学如何读写json文件及json文件转换方法:
https://www.cnblogs.com/XhyTechnologyShare/p/12033690.html

以及with open()as f用法和_init_方法:
https://blog.csdn.net/msspark/article/details/86745391

在Mr.心弦的博客里学到一些python基础

学习正则表达式用于匹配优化:
https://www.runoob.com/python/python-reg-expressions.html

三、设计实现流程

首先设置命令行参数并初始化,输入数据;
递归遍历读取json文件,用json.loads()方法将json数据存入数组;
通过正则表达式匹配数组中的字符串转化为字典格式;
将dict序列化之后用json写文件方法创建3个.json文件将数据存入。

四、具体代码实现

# -*- coding: utf-8 -*-

import os
import argparse
import pickle
import re

Events = ("PushEvent", "IssueCommentEvent", "IssuesEvent", "PullRequestEvent" )
# 四种信息类型
hipping = re.compile(r'"type":"(\w+?)".*?actor.*?"login":"(\S+?)".*?repo.*?"name":"(\S+?)"')
# 使用正则表达式


class inputData:
    def __init__(self):
        self.User = {}
        self.Repo = {}
        self.UserRepo = {}  # 初始化记录读取的内存
    @staticmethod
    def parse(file_path: str):
        records = []  # 从json文件中逐行抽取信息存入空间
        with open(file_path, 'r', encoding='utf-8') as f:  # 打开json文件
            for line in f:
                res = hipping.search(line)  # 运用正则表达式匹配有效数据
                if res is None or res[1] not in Events:
                    continue
                records.append(res.groups())
        return records

    def init(self, dirPath: str):
        records = []
        for curDir, subDir, filenames in os.walk(dirPath):
            filenames = filter(lambda r: r.endswith('.json'), filenames)
            for name in filenames:
                # 将列表扩展拼合
                records.extend(self.parse(f'{curDir}/{name}'))

        for record in records:
            event, user, repo = record
            self.User.setdefault(user, {})
            self.UserRepo.setdefault(user, {})
            self.Repo.setdefault(repo, {})
            self.UserRepo[user].setdefault(repo, {})
            self.User[user][event] = self.User[user].get(event, 0)+1  # 如果不存在就初始化为0,存在就自身+1
            self.Repo[repo][event] = self.Repo[repo].get(event, 0)+1
            self.UserRepo[user][repo][event] = self.UserRepo[user][repo].get(event, 0)+1
        with open('1.json', 'wb') as f:  # 字典转为字符串并将数据写入1、2、3.json
            pickle.dump(self.User, f)
        with open('2.json', 'wb') as f:
            pickle.dump(self.Repo, f)
        with open('3.json', 'wb') as f:
            pickle.dump(self.UserRepo, f)

    def load(self):
        if not any((os.path.exists(f'{i}.json') for i in range(1, 3))):
            raise RuntimeError('error: data file not found')

        with open('1.json', 'rb') as f:
            self.User = pickle.load(f)
        with open('2.json', 'rb') as f:
            self.Repo = pickle.load(f)
        with open('3.json', 'rb') as f:
            self.UserRepo = pickle.load(f)

    def getUser(self, user: str, event: str) -> int:
        return self.User.get(user, {}).get(event, 0)

    def getRepo(self, repo: str, event: str) -> int:
        return self.Repo.get(repo, {}).get(event, 0)

    def getUserRepo(self, user: str, repo: str, event: str) -> int:
        return self.UserRepo.get(user, {}).get(repo, {}).get(event, 0)


class Run:
    # 参数
    def __init__(self):
        self.parser = argparse.ArgumentParser()
        self.data = None
        self.argInit()

    def argInit(self):
        self.parser.add_argument('-i', '--init', type=str)
        self.parser.add_argument('-u', '--user', type=str)
        self.parser.add_argument('-r', '--repo', type=str)
        self.parser.add_argument('-e', '--event', type=str)

    def analyse(self):
        args = self.parser.parse_args()

        self.data = inputData()
        if args.init:
            self.data.init(args.init)
            return 'init done'
        self.data.load()

        if not args.event:
            raise RuntimeError('error: the following arguments are required: -e/--event')
        if not args.user and not args.repo:
            raise RuntimeError('error: the following arguments are required: -u/--user or -r/--repo')

        if args.user and args.repo:
            res = self.data.getUserRepo(args.user, args.repo, args.event)
        elif args.user:
            res = self.data.getUser(args.user, args.event)
        else:
            res = self.data.getRepo(args.repo, args.event)
        return res


if __name__ == '__main__':
    a = Run()
    print(a.analyse())

五、代码规范规则链接

  https://github.com/yezhaoting/software-engineering/blob/master/codestyle.md

六、总结&后记

  这次作业对我来说是非常有难度的,以至于单元测试和覆盖率优化都毫无头绪,这让我更加强烈地感受到和dalao们的差距。不过这次作业对于我的代码能力是一次很好的锻炼,对如何成为一个合格的程序员有了一些了解,希望下一次能够圆满地完成任务。
posted @ 2020-09-16 22:50  yezhaoting  阅读(117)  评论(1编辑  收藏  举报