├── .github └── hypertrons.json ├── .gitignore ├── DataSheets.xlsx ├── LICENSE ├── README.md ├── REPORT.md ├── chinese ├── chinese_company ├── network ├── 996.ICU │ └── bipartite_network │ │ ├── .ipynb_checkpoints │ │ ├── 1-checkpoint.html │ │ ├── 3-checkpoint.html │ │ └── full_year-2019-checkpoint.html │ │ ├── 1.html │ │ ├── 10.html │ │ ├── 11.html │ │ ├── 12.html │ │ ├── 2.html │ │ ├── 3.html │ │ ├── 4.html │ │ ├── 5.html │ │ ├── 6.html │ │ ├── 7.html │ │ ├── 8.html │ │ ├── 9.html │ │ └── full_year-2019.html ├── Daily-Interview-Question │ └── bipartite_network │ │ ├── .ipynb_checkpoints │ │ └── full_year-2019-checkpoint.html │ │ ├── 1.html │ │ ├── 10.html │ │ ├── 11.html │ │ ├── 12.html │ │ ├── 2.html │ │ ├── 3.html │ │ ├── 4.html │ │ ├── 5.html │ │ ├── 6.html │ │ ├── 7.html │ │ ├── 8.html │ │ ├── 9.html │ │ └── full_year-2019.html ├── Paddle │ └── bipartite_network │ │ ├── .ipynb_checkpoints │ │ ├── 1-checkpoint.html │ │ ├── 12-checkpoint.html │ │ ├── 2-checkpoint.html │ │ ├── 3-checkpoint.html │ │ ├── 4-checkpoint.html │ │ ├── 5-checkpoint.html │ │ ├── 6-checkpoint.html │ │ ├── 7-checkpoint.html │ │ ├── 8-checkpoint.html │ │ ├── 9-checkpoint.html │ │ └── full_year-2019-checkpoint.html │ │ ├── 1.html │ │ ├── 10.html │ │ ├── 11.html │ │ ├── 12.html │ │ ├── 2.html │ │ ├── 3.html │ │ ├── 4.html │ │ ├── 5.html │ │ ├── 6.html │ │ ├── 7.html │ │ ├── 8.html │ │ ├── 9.html │ │ └── full_year-2019.html ├── ant-design-pro │ └── bipartite_network │ │ ├── .ipynb_checkpoints │ │ └── full_year-2019-checkpoint.html │ │ ├── 1.html │ │ ├── 10.html │ │ ├── 11.html │ │ ├── 12.html │ │ ├── 2.html │ │ ├── 3.html │ │ ├── 4.html │ │ ├── 5.html │ │ ├── 6.html │ │ ├── 7.html │ │ ├── 8.html │ │ ├── 9.html │ │ └── full_year-2019.html ├── ant-design │ └── bipartite_network │ │ ├── .ipynb_checkpoints │ │ ├── 1-checkpoint.html │ │ ├── 3-checkpoint.html │ │ ├── 6-checkpoint.html │ │ └── full_year-2019-checkpoint.html │ │ ├── 1.html │ │ ├── 10.html │ │ ├── 11.html │ │ ├── 12.html │ │ ├── 2.html │ │ ├── 3.html │ │ ├── 4.html │ │ ├── 5.html │ │ ├── 6.html │ │ ├── 7.html │ │ ├── 8.html │ │ ├── 9.html │ │ └── full_year-2019.html ├── apollo │ └── bipartite_network │ │ ├── .ipynb_checkpoints │ │ ├── 10-checkpoint.html │ │ └── full_year-2019-checkpoint.html │ │ ├── 1.html │ │ ├── 10.html │ │ ├── 11.html │ │ ├── 12.html │ │ ├── 2.html │ │ ├── 3.html │ │ ├── 4.html │ │ ├── 5.html │ │ ├── 6.html │ │ ├── 7.html │ │ ├── 8.html │ │ ├── 9.html │ │ └── full_year-2019.html ├── dubbo │ └── bipartite_network │ │ ├── .ipynb_checkpoints │ │ └── 11-checkpoint.html │ │ ├── 1.html │ │ ├── 10.html │ │ ├── 11.html │ │ ├── 12.html │ │ ├── 2.html │ │ ├── 3.html │ │ ├── 4.html │ │ ├── 5.html │ │ ├── 6.html │ │ ├── 7.html │ │ ├── 8.html │ │ ├── 9.html │ │ └── full_year-2019.html ├── element │ └── bipartite_network │ │ ├── .ipynb_checkpoints │ │ └── full_year-2019-checkpoint.html │ │ ├── 1.html │ │ ├── 10.html │ │ ├── 11.html │ │ ├── 12.html │ │ ├── 2.html │ │ ├── 3.html │ │ ├── 4.html │ │ ├── 5.html │ │ ├── 6.html │ │ ├── 7.html │ │ ├── 8.html │ │ ├── 9.html │ │ └── full_year-2019.html ├── gold-miner │ └── bipartite_network │ │ ├── .ipynb_checkpoints │ │ └── full_year-2019-checkpoint.html │ │ ├── 1.html │ │ ├── 10.html │ │ ├── 11.html │ │ ├── 12.html │ │ ├── 2.html │ │ ├── 3.html │ │ ├── 4.html │ │ ├── 5.html │ │ ├── 6.html │ │ ├── 7.html │ │ ├── 8.html │ │ ├── 9.html │ │ └── full_year-2019.html ├── incubator-echarts │ └── bipartite_network │ │ ├── .ipynb_checkpoints │ │ ├── 1-checkpoint.html │ │ ├── 12-checkpoint.html │ │ ├── 2-checkpoint.html │ │ ├── 8-checkpoint.html │ │ ├── 9-checkpoint.html │ │ └── full_year-2019-checkpoint.html │ │ ├── 1.html │ │ ├── 10.html │ │ ├── 11.html │ │ ├── 12.html │ │ ├── 2.html │ │ ├── 3.html │ │ ├── 4.html │ │ ├── 5.html │ │ ├── 6.html │ │ ├── 7.html │ │ ├── 8.html │ │ ├── 9.html │ │ └── full_year-2019.html ├── nacos │ └── bipartite_network │ │ ├── .ipynb_checkpoints │ │ └── full_year-2019-checkpoint.html │ │ ├── 1.html │ │ ├── 10.html │ │ ├── 11.html │ │ ├── 12.html │ │ ├── 2.html │ │ ├── 3.html │ │ ├── 4.html │ │ ├── 5.html │ │ ├── 6.html │ │ ├── 7.html │ │ ├── 8.html │ │ ├── 9.html │ │ └── full_year-2019.html ├── nest │ └── bipartite_network │ │ ├── .ipynb_checkpoints │ │ ├── 1-checkpoint.html │ │ └── full_year-2019-checkpoint.html │ │ ├── 1.html │ │ ├── 10.html │ │ ├── 11.html │ │ ├── 12.html │ │ ├── 2.html │ │ ├── 3.html │ │ ├── 4.html │ │ ├── 5.html │ │ ├── 6.html │ │ ├── 7.html │ │ ├── 8.html │ │ ├── 9.html │ │ └── full_year-2019.html ├── openapi-generator │ └── bipartite_network │ │ ├── .ipynb_checkpoints │ │ └── full_year-2019-checkpoint.html │ │ ├── 1.html │ │ ├── 10.html │ │ ├── 11.html │ │ ├── 12.html │ │ ├── 2.html │ │ ├── 3.html │ │ ├── 4.html │ │ ├── 5.html │ │ ├── 6.html │ │ ├── 7.html │ │ ├── 8.html │ │ ├── 9.html │ │ └── full_year-2019.html ├── seata │ └── bipartite_network │ │ ├── .ipynb_checkpoints │ │ └── full_year-2019-checkpoint.html │ │ ├── 1.html │ │ ├── 10.html │ │ ├── 11.html │ │ ├── 12.html │ │ ├── 2.html │ │ ├── 3.html │ │ ├── 4.html │ │ ├── 5.html │ │ ├── 6.html │ │ ├── 7.html │ │ ├── 8.html │ │ ├── 9.html │ │ └── full_year-2019.html ├── selfteaching-python-camp │ └── bipartite_network │ │ └── full_year-2019.html ├── skywalking │ └── bipartite_network │ │ ├── .ipynb_checkpoints │ │ ├── 1-checkpoint.html │ │ ├── 12-checkpoint.html │ │ ├── 2-checkpoint.html │ │ ├── 8-checkpoint.html │ │ └── full_year-2019-checkpoint.html │ │ ├── 1.html │ │ ├── 10.html │ │ ├── 11.html │ │ ├── 12.html │ │ ├── 2.html │ │ ├── 3.html │ │ ├── 4.html │ │ ├── 5.html │ │ ├── 6.html │ │ ├── 7.html │ │ ├── 8.html │ │ ├── 9.html │ │ └── full_year-2019.html ├── taro │ └── bipartite_network │ │ ├── .ipynb_checkpoints │ │ ├── 11-checkpoint.html │ │ └── full_year-2019-checkpoint.html │ │ ├── 1.html │ │ ├── 10.html │ │ ├── 11.html │ │ ├── 12.html │ │ ├── 2.html │ │ ├── 3.html │ │ ├── 4.html │ │ ├── 5.html │ │ ├── 6.html │ │ ├── 7.html │ │ ├── 8.html │ │ ├── 9.html │ │ └── full_year-2019.html ├── tidb │ └── bipartite_network │ │ ├── .ipynb_checkpoints │ │ └── full_year-2019-checkpoint.html │ │ ├── 1.html │ │ ├── 10.html │ │ ├── 11.html │ │ ├── 12.html │ │ ├── 2.html │ │ ├── 3.html │ │ ├── 4.html │ │ ├── 5.html │ │ ├── 6.html │ │ ├── 7.html │ │ ├── 8.html │ │ ├── 9.html │ │ └── full_year-2019.html ├── tikv │ └── bipartite_network │ │ ├── .ipynb_checkpoints │ │ └── full_year-2019-checkpoint.html │ │ ├── 1.html │ │ ├── 10.html │ │ ├── 11.html │ │ ├── 12.html │ │ ├── 2.html │ │ ├── 3.html │ │ ├── 4.html │ │ ├── 5.html │ │ ├── 6.html │ │ ├── 7.html │ │ ├── 8.html │ │ ├── 9.html │ │ └── full_year-2019.html ├── vant │ └── bipartite_network │ │ ├── .ipynb_checkpoints │ │ └── full_year-2019-checkpoint.html │ │ ├── 1.html │ │ ├── 10.html │ │ ├── 11.html │ │ ├── 12.html │ │ ├── 2.html │ │ ├── 3.html │ │ ├── 4.html │ │ ├── 5.html │ │ ├── 6.html │ │ ├── 7.html │ │ ├── 8.html │ │ ├── 9.html │ │ └── full_year-2019.html ├── vue-cli │ └── bipartite_network │ │ ├── .ipynb_checkpoints │ │ ├── 1-checkpoint.html │ │ ├── 11-checkpoint.html │ │ └── full_year-2019-checkpoint.html │ │ ├── 1.html │ │ ├── 10.html │ │ ├── 11.html │ │ ├── 12.html │ │ ├── 2.html │ │ ├── 3.html │ │ ├── 4.html │ │ ├── 5.html │ │ ├── 6.html │ │ ├── 7.html │ │ ├── 8.html │ │ ├── 9.html │ │ └── full_year-2019.html └── vue │ └── bipartite_network │ ├── 1.html │ ├── 10.html │ ├── 11.html │ ├── 12.html │ ├── 2.html │ ├── 3.html │ ├── 4.html │ ├── 5.html │ ├── 6.html │ ├── 7.html │ ├── 8.html │ ├── 9.html │ └── full_year-2019.html ├── package-lock.json ├── package.json ├── src ├── config.ts ├── data.ts ├── index.ts ├── processor.ts └── utils.ts ├── static ├── 996.ICU_03.png ├── 996.ICU_full_year.png ├── activity_distribution_log.png ├── activity_repo.gif ├── activity_user.gif ├── china_opensource_project_language.png ├── chinese_top_20_act.png ├── company_top_act.png ├── global_top_10_dev_act.png ├── global_top_10_dev_cnt.png ├── global_top_10_repo_act.png ├── logins_distribution_log.png ├── tidb_10.png ├── tidb_full_year.png ├── tidb_network.png ├── vue_03.png ├── vue_04.png ├── vue_network.png ├── world_active_project_language.png └── world_participant_project_language.png ├── tsconfig.json └── tslint.json /.github/hypertrons.json: -------------------------------------------------------------------------------- 1 | { 2 | "label_setup": { 3 | "version": 1, 4 | "labels": [ 5 | { 6 | "__merge__": true 7 | }, 8 | { 9 | "name": "pull/approved", 10 | "description": "If a pull is approved, it will be automatically merged", 11 | "color": "008672" 12 | } 13 | ] 14 | }, 15 | "weekly_report": { 16 | "version": 1, 17 | "generateTime": "0 0 12 * * 1" 18 | }, 19 | "role": { 20 | "version": 1, 21 | "roles": [ 22 | { 23 | "name": "committer", 24 | "description": "Committer of the project", 25 | "users": [ 26 | "frank-zsy", 27 | "will-ww", 28 | "JerryKuan" 29 | ], 30 | "commands": [] 31 | }, 32 | { 33 | "name": "replier", 34 | "description": "Replier is responsible for reply issues in time", 35 | "users": [ 36 | "frank-zsy", 37 | "JerryKuan" 38 | ], 39 | "commands": [] 40 | }, 41 | { 42 | "name": "approver", 43 | "description": "After approvers' approve, pulls should be merged automatically", 44 | "users": [ 45 | "frank-zsy", 46 | "will-ww", 47 | "JerryKuan" 48 | ], 49 | "commands": [ 50 | "/approve" 51 | ] 52 | }, 53 | { 54 | "name": "author", 55 | "description": "Author of the issue or pull", 56 | "users": [], 57 | "commands": [] 58 | }, 59 | { 60 | "name": "notauthor", 61 | "description": "Not author of the issue or pull", 62 | "users": [], 63 | "commands": [ 64 | "/approve" 65 | ] 66 | }, 67 | { 68 | "name": "anyone", 69 | "description": "Anyone", 70 | "users": [], 71 | "commands": [ 72 | "/self-assign" 73 | ] 74 | } 75 | ] 76 | }, 77 | "command": { 78 | "version": 1, 79 | "commands": [ 80 | { 81 | "name": "/approve", 82 | "scopes": [ 83 | "review", 84 | "review_comment", 85 | "pull_comment" 86 | ] 87 | } 88 | ] 89 | }, 90 | "approve": { 91 | "version": 1 92 | }, 93 | "auto_merge": { 94 | "version": 1, 95 | "sched": "0 */5 * * * *" 96 | }, 97 | "issue_reminder": { 98 | "version": 1 99 | }, 100 | "auto_label": { 101 | "version": 1 102 | }, 103 | "self_assign": { 104 | "version": 1 105 | } 106 | } 107 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | logs/ 2 | npm-debug.log 3 | node_modules/ 4 | coverage/ 5 | .idea/ 6 | run/ 7 | logs/ 8 | .DS_Store 9 | .vscode 10 | *.swp 11 | *.lock 12 | *.js 13 | lib/ 14 | output*.csv 15 | .cache_* 16 | data 17 | bin 18 | ~* 19 | -------------------------------------------------------------------------------- /DataSheets.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/X-lab2017/github-analysis-report-2019/c7e33924561c15626d0e1b3bf9e58ae118b40057/DataSheets.xlsx -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 X-lab 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 6 | 7 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 8 | 9 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 10 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # GitHub 2019 数据年报 2 | 3 | ## 简介 4 | 5 | 在开源日益重要的今天,我们需要一份建立在全域大数据基础上的相对完整、可以反复进行推演的数据报告(报告、数据、算法均需开源)。本项目为X-lab 开放实验室团队发起,旨在通过分析Github全网的开发者行为日志,通过数据的视角,来观察全球范围内的开源现状、进展趋势、演化特征、以及未来挑战等问题,除了展现目前开源世界全貌之外,我们特别关注中国的开发者和企业组织在整个开源产业中的表现。本报告中使用 2019 年全年 GitHub 日志进行统计,总日志条数约 5.46 亿条。 6 | 7 | **关键词**:开源、行为数据、开发者行为、Github、数字报告 8 | 9 | ## 数据年报 10 | 11 | 关于数据年报,请点击[《GitHub 2019 数字年报全文》](./REPORT.md)。 12 | 13 | 本报告使用 2019 年全年 GitHub 日志进行统计,总日志条数约 5.46 亿条,相较 2018 年的 4.21 亿条增长约 29.7%。在上述开发者活跃度与项目活跃度的定义下,统计得到 2019 年总活跃项目数量约 512W 个,相较 2018 年的约 313W 增长约 63.6%,2019 年总活跃开发者数量约 360W,相较 2018 年的约 303W 增长约 18.8%。 14 | 15 | **世界 Top 10 开发者账号** 16 | 17 | ![global_top_10_dev_act](./static/global_top_10_dev_act.png) 18 | 19 | **世界 Top 10 项目** 20 | 21 | ![global_top_10_dev_act](./static/global_top_10_repo_act.png) 22 | 23 | **中国 Top 20 项目分析** 24 | 25 | ![chinese_top_20_act](./static/chinese_top_20_act.png) 26 | 27 | ## 原始数据 28 | 29 | 关于数据,请访问[CDN](http://cdn.opensource-service.cn/github-analysis-report-2019/data.json.gz) 30 | 31 | 由于原始的日志文本数据数据量较大(约 1.45TB),故随本文开放的数据为统计处理并压缩后的数据文件,总大小约为 225MB,解压后文件内容为文本内容,总大小约 1.3GB,总行数约 2169 万行。每行为一个记录项,由 Json格式编码,该文件不再区分具体日期,直接给出每个账号在每个项目中的2019全年的操作次数,以方便处理。内容说明如下: 32 | 33 | | 字段 | 类型 | 说明 | 34 | | ---- | ------ | -------- | 35 | | r | string | 项目名称 | 36 | | u | string | 账号名称 | 37 | | t | number | 操作类型 | 38 | | c | number | 操作次数 | 39 | 40 | 41 | 42 | ## 分析程序 43 | 44 | 分析程序使用命令: 45 | 46 | ```shell 47 | $npm i 48 | $npm start -- --help 49 | $npm start 50 | ``` 51 | 52 | 在使用 `npm start -- --help` 后可以看到相关的帮助信息,内容如下: 53 | 54 | ```shell 55 | Options: 56 | --help Show help [boolean] 57 | --version Show version number [boolean] 58 | -f Origin data file path [string] [default: "./data/data.json.gz"] 59 | -c Issue comment weight [number] [default: 1] 60 | -i Open issue weight [number] [default: 2] 61 | -p Open PR weight [number] [default: 3] 62 | -r Review comment weight [number] [default: 4] 63 | -m PR merged weight [number] [default: 5] 64 | -n Output repo count [number] [default: 10] 65 | --detail Whether show detail data [boolean] [default: false] 66 | --detailn Number to print for detail data [number] [default: 10] 67 | --mode Output mode [choices: "repo", "dev", "company"] [default: "repo"] 68 | --search Search items to output [array] [default: []] 69 | --compTop Show top N count for company [array] [default: [500,10000]] 70 | --sort Order by activity or repo/developer count 71 | [choices: "act", "cnt"] [default: "act"] 72 | --ch Only show chinese repos [boolean] [default: false] 73 | ``` 74 | 75 | 其中 `-f` 为数据文件所在路径,默认路径为 `./data/data.json.gz`,故下载数据文件后放在该路径下,则不需要指定 `-f` 参数,否则可以自行指定文件所在路径。 76 | 77 | 在计算模型中,Comment、Open Issue、Open PR、Review Comment、Merge PR 对应的权重默认为 1、2、3、4、5,可以通过启动选项 `-c, -i, -p, -r, -m` 来分别修改对应权重,以获取定制权重的排行结果。 78 | 79 | `--mode` 为主要的设置参数之一,表示分析类型,可以为 `repo, dev, company` 之一,默认为 `repo`。当为 `repo` 时分析结果以仓库为主体,当为 `dev` 时结果以开发者为主体,当为 `company` 时结果以公司为主体。其中 `company` 与仓库之间的关联通过 [`chinese_company`](./chinese_company) 文件定义,文件中每一个空行隔开的一个部分为一个完整的公司,块内第一行为公司名,其后为跟随的项目或组织的名称,大小写敏感。`-n` 参数决定最终输出结果时输出 Top n。 80 | 81 | `--detail` 表示输出时为详情模式,在不同的 `--mode` 下,详情模式输出的内容也不相同。在 `repo` 模式下,详情模式会在输出 Top `-n` 的同时,输出每个项目中 Top `--detailN` 个开发者的统计信息。在 `dev` 模式下,详情模式会在输出 Top `-n` 的同时,输出每个开发者参与的项目中活跃度 Top `--detailN` 的项目及对应的统计信息。 在 `company` 模式下,详情模式会在输出 Top `-n` 的同时,输出每个企业中 Top `--detailN` 个项目的详情。 82 | 83 | 在 `--mode` 为 `company` 时,可以通过设置 `--compTop` 来输出该企业的所有项目在世界 Top N 中的项目数量,默认会输出 Top 500 和 Top 10000 中的项目数量。 84 | 85 | 在指定 `--search` 时,可以搜索对应模式下的项目或开发者账号的信息,支持同时搜索多个,并使用正则匹配。 86 | 87 | 通过修改 `--sort` 选项为 `cnt`,可以修改排名方式,默认 `act` 排名模式下,项目与开发者以活跃度排名,`cnt` 排名模式下,项目与开发者分别以参与项目人数和参与项目个数排名。 88 | 89 | 若仅关注中国项目情况,可以通过打开 `--ch` 选项,中国项目的筛选通过指定 org 或 repo 名称的方式,内容为 [`chinese`](./chinese) 文件和 [`chinese_company`](./chinese_company) 文件中的项目并集,目前为人工标注方式。 90 | -------------------------------------------------------------------------------- /chinese: -------------------------------------------------------------------------------- 1 | vuejs 2 | selfteaching 3 | OpenAPITools 4 | gogs 5 | Advanced-Frontend 6 | apache/skywalking 7 | apache/incubator-apisix 8 | nestjs 9 | 996icu 10 | swoole 11 | flutterchina 12 | James-Yu 13 | shadowsocks/ShadowsocksX-NG 14 | ccyyycy 15 | fatedier 16 | RT-Thread 17 | ruanyf 18 | emqx 19 | dotnet/docfx 20 | apache/incubator-dolphinscheduler 21 | CarGuo 22 | recharts/recharts 23 | jdcloudcom 24 | kubesphere 25 | xingyizhou 26 | hexojs 27 | algorithm004-05 28 | a13112165035 29 | LuClass 30 | qqwweee 31 | apache/incubator-doris 32 | algorithm004-03 33 | neolee 34 | umijs 35 | consenlabs/token-profile 36 | PanJiaChen 37 | apache/incubator-tvm 38 | coolsnowwolf 39 | open-mmlab 40 | XX-net 41 | DIYgod 42 | baomidou 43 | iview 44 | haizlin 45 | michaelliao 46 | vueComponent 47 | NG-ZORRO 48 | z-song 49 | dcloudio 50 | testerSunshine 51 | neoclide/coc.nvim 52 | hzuapps 53 | YMFE 54 | komeiji-satori 55 | jinzhu 56 | xuxueli 57 | syhyz1990 58 | taichi-framework 59 | jumpserver 60 | shadowsocks/shadowsocks-windows 61 | Alivon 62 | gitalk 63 | deepinsight 64 | MiEcosystem 65 | taosdata 66 | OI-wiki 67 | YunYang1994 68 | hyperf 69 | zhangdaiscott 70 | RikkaApps 71 | algorithm004-01 72 | -------------------------------------------------------------------------------- /chinese_company: -------------------------------------------------------------------------------- 1 | Alibaba 2 | alibaba 3 | aliyun 4 | alipay 5 | taobao 6 | thx 7 | kissyteam 8 | ant-design 9 | antvis 10 | kissygalleryteam 11 | seajs 12 | midwayjs 13 | ali-sdk 14 | cnpm 15 | hiloteam 16 | eggjs 17 | macacajs 18 | ElemeFE 19 | youkuvip 20 | dvajs 21 | seata 22 | dragonflyoss 23 | sofastack 24 | chaosblade-io 25 | AliyunContainerService 26 | aliqin 27 | AlibabaCloudDocs 28 | sentinel-group 29 | unijs 30 | mars-project 31 | node-honeycomb 32 | apache/dubbo 33 | apache/incubator-weex 34 | apache/rocketmq 35 | 36 | Baidu 37 | baidu 38 | PaddlePaddle 39 | ApolloAuto 40 | Clouda-team 41 | mipengine 42 | mesalock-linux 43 | ecomfe 44 | fex-team 45 | baidu-research 46 | huiyan-fe 47 | be-fe 48 | swan-team 49 | apache/incubator-echarts 50 | apache/incubator-brpc 51 | 52 | Tencent 53 | Tencent 54 | Alloyteam 55 | TarsCloud 56 | weixin 57 | tencentyun 58 | 59 | Huawei 60 | Huawei 61 | huawei-cloudnative 62 | huaweicloud 63 | kubeedge 64 | kubegene 65 | Liteos 66 | huawei-noah 67 | apache/servicecomb-pack 68 | apache/servicecomb-java-chassis 69 | apache/servicecomb-service-center 70 | 71 | Meituan 72 | meituan 73 | Meituan-Dianping 74 | dianping 75 | 76 | 360 77 | Qihoo360 78 | spritejs 79 | thinkjs 80 | Chimeejs 81 | 75team 82 | 0Kee-Team 83 | 84 | Xiaomi 85 | XiaoMi 86 | MiCode 87 | 88 | PingCAP 89 | pingcap 90 | tikv 91 | 92 | Youzan 93 | youzan 94 | 95 | JD 96 | areslabs 97 | NervJS 98 | jdf2e 99 | apache/incubator-shardingsphere 100 | 101 | Bytedance 102 | bytedance 103 | 104 | Netease 105 | NetEase 106 | netease-im 107 | AirtestProject 108 | 163yun 109 | 110 | DiDi 111 | didi 112 | 113 | Vipshop 114 | vipshop 115 | 116 | Deepin 117 | linuxdeepin 118 | 119 | WeBank 120 | WeBankFinTech 121 | 122 | Douban 123 | douban 124 | 125 | Linux China 126 | LCTT 127 | 128 | CTrip 129 | ctripcorp 130 | 131 | Qunar 132 | qunarcorp 133 | 134 | Juejin 135 | xitu 136 | 137 | Bilibili 138 | bilibili 139 | -------------------------------------------------------------------------------- /network/996.ICU/bipartite_network/.ipynb_checkpoints/1-checkpoint.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 24 | 25 | 26 | [save svg] 28 | 29 | 30 | 31 | 215 | -------------------------------------------------------------------------------- /network/996.ICU/bipartite_network/1.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 24 | 25 | 26 | [save svg] 28 | 29 | 30 | 31 | 215 | -------------------------------------------------------------------------------- /network/996.ICU/bipartite_network/10.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 24 | 25 | 26 | [save svg] 28 | 29 | 30 | 31 | 215 | -------------------------------------------------------------------------------- /network/996.ICU/bipartite_network/11.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 24 | 25 | 26 | [save svg] 28 | 29 | 30 | 31 | 215 | -------------------------------------------------------------------------------- /network/996.ICU/bipartite_network/12.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 24 | 25 | 26 | [save svg] 28 | 29 | 30 | 31 | 215 | -------------------------------------------------------------------------------- /network/996.ICU/bipartite_network/2.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 24 | 25 | 26 | [save svg] 28 | 29 | 30 | 31 | 215 | -------------------------------------------------------------------------------- /network/Daily-Interview-Question/bipartite_network/1.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 24 | 25 | 26 | [save svg] 28 | 29 | 30 | 31 | 215 | -------------------------------------------------------------------------------- /network/Daily-Interview-Question/bipartite_network/10.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 24 | 25 | 26 | [save svg] 28 | 29 | 30 | 31 | 215 | -------------------------------------------------------------------------------- /network/Daily-Interview-Question/bipartite_network/11.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 24 | 25 | 26 | [save svg] 28 | 29 | 30 | 31 | 215 | -------------------------------------------------------------------------------- /network/Daily-Interview-Question/bipartite_network/12.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 24 | 25 | 26 | [save svg] 28 | 29 | 30 | 31 | 215 | -------------------------------------------------------------------------------- /network/Daily-Interview-Question/bipartite_network/2.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 24 | 25 | 26 | [save svg] 28 | 29 | 30 | 31 | 215 | -------------------------------------------------------------------------------- /network/Daily-Interview-Question/bipartite_network/6.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 24 | 25 | 26 | [save svg] 28 | 29 | 30 | 31 | 215 | -------------------------------------------------------------------------------- /network/Daily-Interview-Question/bipartite_network/8.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 24 | 25 | 26 | [save svg] 28 | 29 | 30 | 31 | 215 | -------------------------------------------------------------------------------- /network/Daily-Interview-Question/bipartite_network/9.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 24 | 25 | 26 | [save svg] 28 | 29 | 30 | 31 | 215 | -------------------------------------------------------------------------------- /network/element/bipartite_network/12.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 24 | 25 | 26 | [save svg] 28 | 29 | 30 | 31 | 215 | -------------------------------------------------------------------------------- /network/incubator-echarts/bipartite_network/.ipynb_checkpoints/1-checkpoint.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 24 | 25 | 26 | [save svg] 28 | 29 | 30 | 31 | 215 | -------------------------------------------------------------------------------- /network/incubator-echarts/bipartite_network/.ipynb_checkpoints/12-checkpoint.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 24 | 25 | 26 | [save svg] 28 | 29 | 30 | 31 | 215 | -------------------------------------------------------------------------------- /network/incubator-echarts/bipartite_network/.ipynb_checkpoints/8-checkpoint.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 24 | 25 | 26 | [save svg] 28 | 29 | 30 | 31 | 215 | -------------------------------------------------------------------------------- /network/incubator-echarts/bipartite_network/.ipynb_checkpoints/9-checkpoint.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 24 | 25 | 26 | [save svg] 28 | 29 | 30 | 31 | 215 | -------------------------------------------------------------------------------- /network/incubator-echarts/bipartite_network/.ipynb_checkpoints/full_year-2019-checkpoint.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 24 | 25 | 26 | [save svg] 28 | 29 | 30 | 31 | 215 | -------------------------------------------------------------------------------- /network/seata/bipartite_network/3.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 24 | 25 | 26 | [save svg] 28 | 29 | 30 | 31 | 215 | -------------------------------------------------------------------------------- /network/vue/bipartite_network/11.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 24 | 25 | 26 | [save svg] 28 | 29 | 30 | 31 | 215 | -------------------------------------------------------------------------------- /network/vue/bipartite_network/6.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 24 | 25 | 26 | [save svg] 28 | 29 | 30 | 31 | 215 | -------------------------------------------------------------------------------- /network/vue/bipartite_network/7.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 24 | 25 | 26 | [save svg] 28 | 29 | 30 | 31 | 215 | -------------------------------------------------------------------------------- /network/vue/bipartite_network/9.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 24 | 25 | 26 | [save svg] 28 | 29 | 30 | 31 | 215 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "github-analysis-report-2019", 3 | "version": "1.0.0", 4 | "description": "GitHub analysis report 2019 via X-lab", 5 | "main": "lib/index.js", 6 | "bin": "lib/index.js", 7 | "scripts": { 8 | "start": "npm run build && node --max_old_space_size=12288 lib/index.js", 9 | "build": "tsc", 10 | "pkg": "pkg package.json -t node10-win-x64,node10-linux-x64,node10-macos-x64 --out-path=./bin/" 11 | }, 12 | "keywords": [ 13 | "GitHub", 14 | "Data", 15 | "analysis" 16 | ], 17 | "author": "X-lab", 18 | "license": "MIT", 19 | "dependencies": { 20 | "tslib": "^1.10.0", 21 | "typescript": "^3.7.4", 22 | "yargs": "^15.1.0" 23 | }, 24 | "devDependencies": { 25 | "@types/node": "^13.1.4", 26 | "@types/yargs": "^13.0.4", 27 | "pkg": "^4.4.2", 28 | "tslint": "^5.20.1" 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/config.ts: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | export type Mode = 'repo' | 'dev' | 'company'; 4 | export type Sort = 'act' | 'cnt'; 5 | 6 | interface IConfig { 7 | issueCommentWeight: number; 8 | openIssueWeight: number; 9 | openPullWeight: number; 10 | reviewCommentWeight: number; 11 | pullMergedWeight: number; 12 | dataFilePath: string; 13 | outputRepoCount: number; 14 | onlyChineseRepos: boolean; 15 | outputMode: Mode; 16 | sortMode: Sort; 17 | searchItems: string[]; 18 | showDetail: boolean; 19 | detailNum: number; 20 | companyTopN: number[]; 21 | } 22 | 23 | const config: IConfig = { 24 | issueCommentWeight: 1, 25 | openIssueWeight: 2, 26 | openPullWeight: 3, 27 | reviewCommentWeight: 4, 28 | pullMergedWeight: 5, 29 | dataFilePath: './data/data.json.gz', 30 | outputRepoCount: 10, 31 | onlyChineseRepos: false, 32 | outputMode: 'repo', 33 | sortMode: 'act', 34 | searchItems: [], 35 | showDetail: false, 36 | detailNum: 10, 37 | companyTopN: [500, 10000], 38 | }; 39 | 40 | export default config; 41 | -------------------------------------------------------------------------------- /src/data.ts: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | import { Sort } from './config'; 4 | 5 | export enum OperationType { 6 | ISSUE_COMMNT, 7 | OPEN_ISSUE, 8 | OPEN_PULL, 9 | REVIEW_COMMENT, 10 | MERGE_PULL, 11 | } 12 | 13 | export interface IRecordStructure { 14 | [key: string]: Array<{ 15 | u: string; 16 | c: number[]; 17 | }>; 18 | } 19 | 20 | class TypeData { 21 | public name: string; 22 | public opCount: Map; 23 | public activity: number; 24 | 25 | constructor(name: string) { 26 | this.name = name; 27 | this.opCount = new Map(); 28 | } 29 | 30 | public set(t: OperationType, c: number) { 31 | this.opCount.set(t, c); 32 | } 33 | 34 | public calc(weightMap: Map) { 35 | this.activity = 0; 36 | this.opCount.forEach((c, type) => { 37 | const weight = weightMap.get(type); 38 | this.activity += c * weight; 39 | }); 40 | } 41 | } 42 | 43 | export class DetailData { 44 | public name: string; 45 | public activity: number; 46 | public sortedData: TypeData[]; 47 | public opCount: Map; 48 | public data: Map; 49 | 50 | constructor(name: string) { 51 | this.name = name; 52 | this.activity = 0; 53 | this.data = new Map(); 54 | this.sortedData = null; 55 | this.opCount = new Map(); 56 | } 57 | 58 | public set(k: string, c: number, t: OperationType) { 59 | if (!this.data.has(k)) { 60 | this.data.set(k, new TypeData(k)); 61 | } 62 | this.data.get(k).set(t, c); 63 | } 64 | 65 | public calc(weightMap: Map) { 66 | this.activity = 0; 67 | this.data.forEach((d) => { 68 | d.calc(weightMap); 69 | this.activity += Math.sqrt(d.activity); 70 | for (let t = OperationType.ISSUE_COMMNT; t <= OperationType.MERGE_PULL; t++) { 71 | this.opCount.set(t, (this.opCount.get(t) ?? 0) + (d.opCount.get(t) ?? 0)); 72 | } 73 | }); 74 | this.activity = Math.round(this.activity); 75 | } 76 | 77 | public sort() { 78 | this.sortedData = Array.from(this.data.values()).sort((a, b) => b.activity - a.activity); 79 | } 80 | } 81 | 82 | export default class Data { 83 | public sortedData: DetailData[]; 84 | public opCount: Map; 85 | private data: Map; 86 | 87 | constructor() { 88 | this.data = new Map(); 89 | this.sortedData = null; 90 | this.opCount = new Map(); 91 | } 92 | 93 | public set(k1: string, k2: string, c: number, type: OperationType) { 94 | if (!this.data.has(k1)) { 95 | this.data.set(k1, new DetailData(k1)); 96 | } 97 | this.data.get(k1).set(k2, c, type); 98 | } 99 | 100 | public calc(weightMap: Map, sort: Sort): void { 101 | this.data.forEach((d) => { 102 | d.calc(weightMap); 103 | for (let t = OperationType.ISSUE_COMMNT; t <= OperationType.MERGE_PULL; t++) { 104 | this.opCount.set(t, (this.opCount.get(t) ?? 0) + (d.opCount.get(t) ?? 0)); 105 | } 106 | }); 107 | if (sort === 'act') { 108 | this.sortedData = Array.from(this.data.values()).sort((a, b) => b.activity - a.activity); 109 | } else if (sort === 'cnt') { 110 | this.sortedData = Array.from(this.data.values()).sort((a, b) => b.data.size - a.data.size); 111 | } 112 | } 113 | 114 | public parse(obj: IRecordStructure): void { 115 | this.data = new Map(); 116 | const keys = Object.keys(obj); 117 | keys.forEach((k) => { 118 | const r = obj[k]; 119 | const detail = new DetailData(k); 120 | r.forEach((v) => { 121 | const { u, c: counts } = v; 122 | counts.forEach((c, t) => { 123 | detail.set(u, c, t); 124 | }); 125 | }); 126 | this.data.set(k, detail); 127 | }); 128 | } 129 | 130 | public toObj(): IRecordStructure { 131 | const obj: IRecordStructure = {}; 132 | this.data.forEach((v, k) => { 133 | obj[k] = Array.from(v.data).map((detail) => { 134 | const m = detail[1].opCount; 135 | return { 136 | u: detail[0], 137 | c: [m.get(OperationType.ISSUE_COMMNT) ?? 0, m.get(OperationType.OPEN_ISSUE) ?? 0, 138 | m.get(OperationType.OPEN_PULL) ?? 0, m.get(OperationType.REVIEW_COMMENT) ?? 0, 139 | m.get(OperationType.MERGE_PULL) ?? 0], 140 | }; 141 | }); 142 | }); 143 | return obj; 144 | } 145 | } 146 | -------------------------------------------------------------------------------- /src/index.ts: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | import { existsSync, writeFileSync } from 'fs'; 4 | import { EOL } from 'os'; 5 | import { isNumber } from 'util'; 6 | import yargs from 'yargs'; 7 | import config, { Sort } from './config'; 8 | import Data, { OperationType } from './data'; 9 | import { Processor } from './processor'; 10 | import { loadChinese, loadChineseCompanies, logger } from './utils'; 11 | 12 | export async function main() { 13 | 14 | yargs.locale('en-us'); 15 | const argv = yargs.options({ 16 | f: { type: 'string', default: config.dataFilePath, desc: 'Origin data file path' }, 17 | c: { type: 'number', default: config.issueCommentWeight, desc: 'Issue comment weight' }, 18 | i: { type: 'number', default: config.openIssueWeight, desc: 'Open issue weight' }, 19 | p: { type: 'number', default: config.openPullWeight, desc: 'Open PR weight' }, 20 | r: { type: 'number', default: config.reviewCommentWeight, desc: 'Review comment weight' }, 21 | m: { type: 'number', default: config.pullMergedWeight, desc: 'PR merged weight' }, 22 | n: { type: 'number', default: config.outputRepoCount, desc: 'Output repo count' }, 23 | detail: { type: 'boolean', default: config.showDetail, desc: 'Whether show detail data' }, 24 | detailn: { type: 'number', default: config.detailNum, desc: 'Number to print for detail data' }, 25 | mode: { choices: ['repo', 'dev', 'company'], default: config.outputMode, desc: 'Output mode' }, 26 | search: { type: 'array', default: config.searchItems, desc: 'Search items to output' }, 27 | compTop: { type: 'array', default: config.companyTopN, desc: 'Show top N count for company' }, 28 | sort: { choices: ['act', 'cnt'], default: config.sortMode, desc: 'Order by activity or repo/developer count' }, 29 | ch: { type: 'boolean', default: config.onlyChineseRepos, desc: 'Only show chinese repos' }, 30 | }).argv; 31 | 32 | if (argv.help) { 33 | yargs.help(); 34 | return; 35 | } 36 | 37 | logger.info('Start to load data file.'); 38 | 39 | if (!existsSync(argv.f)) { 40 | logger.error(`Origin data file not exists, path =`, argv.f); 41 | return; 42 | } 43 | 44 | const processor = new Processor(); 45 | const data = await processor.processFile({ 46 | filePath: argv.f, 47 | mode: argv.mode, 48 | }); 49 | 50 | logger.info('Load file done, start calculating.'); 51 | // set operation weights 52 | const weightMap = new Map() 53 | .set(OperationType.ISSUE_COMMNT, argv.c) 54 | .set(OperationType.OPEN_ISSUE, argv.i) 55 | .set(OperationType.OPEN_PULL, argv.p) 56 | .set(OperationType.REVIEW_COMMENT, argv.r) 57 | .set(OperationType.MERGE_PULL, argv.m); 58 | // calculate the activity 59 | data.calc(weightMap, argv.sort as Sort); 60 | let arr = data.sortedData; 61 | const companyData = new Data(); 62 | 63 | logger.info('Calculate done, total count is', arr.length); 64 | // print out the results 65 | const table = []; 66 | 67 | let filterFunc = (_: string) => true; 68 | if (argv.search.length > 0) { 69 | // add filter func for search items 70 | filterFunc = (name: string): boolean => argv.search.some((s) => name.match(s)); 71 | } 72 | if (argv.mode === 'company') { 73 | // recalculate company data 74 | const companies = Array.from(loadChineseCompanies()); 75 | arr.forEach((item) => { 76 | // repo belongs to a company 77 | const company = companies.find((c) => c[1].some((r) => item.name.startsWith(r))); 78 | if (!company) { return; } 79 | for (let t = OperationType.ISSUE_COMMNT; t <= OperationType.MERGE_PULL; t++) { 80 | companyData.set(company[0], item.name, item.opCount.get(t) ?? 0, t); 81 | } 82 | }); 83 | companyData.calc(weightMap, argv.sort as Sort); 84 | arr = companyData.sortedData; 85 | } else if (argv.mode === 'repo' && argv.ch) { 86 | // add filter func for chinese repos 87 | const prefixes = loadChinese(); 88 | const oldFilter = filterFunc; 89 | filterFunc = (name: string) => prefixes.some((s) => name.startsWith(s)) && oldFilter(name); 90 | } 91 | 92 | const getCountDetail = (opCount: Map): any => { 93 | return { 94 | 'issue comment': opCount.get(OperationType.ISSUE_COMMNT) ?? 0, 95 | 'open issue': opCount.get(OperationType.OPEN_ISSUE) ?? 0, 96 | 'open PR': opCount.get(OperationType.OPEN_PULL) ?? 0, 97 | 'review comment': opCount.get(OperationType.REVIEW_COMMENT) ?? 0, 98 | 'PR merged': opCount.get(OperationType.MERGE_PULL) ?? 0, 99 | }; 100 | }; 101 | let rank = 0; 102 | for (let i = 0; i < arr.length; i++) { 103 | if (argv.n > 0 && rank >= argv.n) { 104 | break; 105 | } 106 | const item = arr[i]; 107 | const globalRank = i + 1; 108 | if (!filterFunc(item.name)) { continue; } 109 | rank++; 110 | 111 | if (argv.detail) { 112 | // show detail data 113 | item.sort(); 114 | item.sortedData.slice(0, argv.detailn).forEach((detail) => { 115 | const t: any = { 116 | '#': rank, 117 | '#Global': globalRank, 118 | 'name': item.name, 119 | 'sub name': detail.name, 120 | 'activity': detail.activity, 121 | ...getCountDetail(detail.opCount), 122 | }; 123 | table.push(t); 124 | }); 125 | } else { 126 | // show brief data 127 | const t: any = { 128 | '#': rank, 129 | '#Global': globalRank, 130 | 'name': item.name, 131 | 'activity': item.activity, 132 | 'count': item.data.size, 133 | ...getCountDetail(item.opCount), 134 | }; 135 | if (argv.mode === 'company') { 136 | // if company mode, add some other factor 137 | if (argv.compTop.length > 0) { 138 | const companyRepos = Array.from(item.data.keys()); 139 | for (const top of argv.compTop) { 140 | if (!isNumber(top)) { 141 | logger.error('Invalid top param', top); 142 | continue; 143 | } 144 | t[`top ${top}`] = companyRepos.filter((r) => 145 | data.sortedData.slice(0, top).map((d) => d.name).includes(r)).length; 146 | } 147 | } 148 | } 149 | table.push(t); 150 | } 151 | } 152 | 153 | logger.info('Process done.'); 154 | if (table.length > 0) { 155 | console.table(table); 156 | // output to file as csv format 157 | const keys = Object.keys(table[0]); 158 | let str = keys.join(',') + EOL; 159 | table.forEach((record) => { 160 | keys.forEach((key) => { 161 | str += record[key] + ','; 162 | }); 163 | str += EOL; 164 | }); 165 | writeFileSync(`output-${new Date()}.csv`, str); 166 | } 167 | 168 | return table; 169 | } 170 | 171 | main(); 172 | -------------------------------------------------------------------------------- /src/processor.ts: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | import { once } from 'events'; 4 | import { createReadStream, existsSync, readFileSync, writeFileSync } from 'fs'; 5 | import { createInterface } from 'readline'; 6 | import { createGunzip, gunzipSync, gzipSync } from 'zlib'; 7 | import { Mode } from './config'; 8 | import Data from './Data'; 9 | import { logger } from './utils'; 10 | 11 | interface IProcessorOptions { 12 | filePath: string; 13 | mode: Mode; 14 | } 15 | 16 | export interface IRecord { 17 | r: string; 18 | u: string; 19 | t: number; 20 | c: number; 21 | } 22 | 23 | export class Processor { 24 | public async processFile(options: IProcessorOptions): Promise { 25 | const data = new Data(); 26 | 27 | const getCacheFilePath = (mode: Mode): string => { 28 | if (mode === 'dev') { 29 | return `.cache_${mode}.gz`; 30 | } else { 31 | return `.cache_repo.gz`; 32 | } 33 | }; 34 | const cacheFilePath = getCacheFilePath(options.mode); 35 | if (existsSync(cacheFilePath)) { 36 | logger.info('Cache file found, path=', cacheFilePath); 37 | const o = JSON.parse(gunzipSync(readFileSync(cacheFilePath)).toString()); 38 | data.parse(o); 39 | return data; 40 | } 41 | 42 | try { 43 | const rl = createInterface({ 44 | crlfDelay: Infinity, 45 | input: createReadStream(options.filePath).pipe(createGunzip()), 46 | }); 47 | 48 | let record: any; 49 | let process: (r: any) => void = (r: any) => { 50 | data.set(r.r, r.u, r.c, r.t); 51 | }; 52 | if (options.mode === 'dev') { 53 | process = (r: any) => { 54 | data.set(r.u, r.r, r.c, r.t); 55 | }; 56 | } 57 | rl.on('line', (line) => { 58 | if (line.length <= 0) { return; } 59 | try { 60 | record = JSON.parse(line); 61 | process(record); 62 | } catch { 63 | logger.info('Parse json fail, line=', line); 64 | } 65 | }); 66 | 67 | await once(rl, 'close'); 68 | } catch (e) { 69 | logger.info('Error during processing file, e =', e); 70 | return data; 71 | } 72 | 73 | const obj = data.toObj(); 74 | writeFileSync(cacheFilePath, gzipSync(JSON.stringify(obj))); 75 | return data; 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /src/utils.ts: -------------------------------------------------------------------------------- 1 | import { readFileSync } from 'fs'; 2 | import { EOL } from 'os'; 3 | 4 | // load all chinese repos prefix array 5 | export function loadChinese(): string[] { 6 | const chineseFilePath = './chinese'; 7 | const chineseCompanyFilePath = './chinese_company'; 8 | 9 | const chinese = readFileSync(chineseFilePath).toString(); 10 | const chinseCompany = readFileSync(chineseCompanyFilePath).toString(); 11 | 12 | const ret: string[] = []; 13 | 14 | const add = (l: string): void => { 15 | if (l.length <= 0) { 16 | return; 17 | } 18 | if (!l.includes('/')) { 19 | l += '/'; 20 | } 21 | ret.push(l); 22 | }; 23 | 24 | chinese.split(EOL).forEach(add); 25 | 26 | let firstLine = true; 27 | chinseCompany.split(EOL).forEach((l) => { 28 | if (firstLine) { 29 | firstLine = false; 30 | return; 31 | } 32 | if (l.length === 0 && !firstLine) { 33 | firstLine = true; 34 | return; 35 | } 36 | add(l); 37 | }); 38 | 39 | return ret; 40 | } 41 | 42 | // load chinese companies 43 | export function loadChineseCompanies(): Map { 44 | const chineseCompanyFilePath = './chinese_company'; 45 | const chinseCompany = readFileSync(chineseCompanyFilePath).toString(); 46 | const ret = new Map(); 47 | 48 | let arr: string[] = []; 49 | const add = (l: string): void => { 50 | if (l.length <= 0) { 51 | return; 52 | } 53 | if (!l.includes('/')) { 54 | l += '/'; 55 | } 56 | arr.push(l); 57 | }; 58 | 59 | let firstLine = true; 60 | let company = ''; 61 | chinseCompany.split(EOL).forEach((l) => { 62 | if (firstLine) { 63 | company = l; 64 | firstLine = false; 65 | return; 66 | } 67 | if (l.length === 0 && !firstLine) { 68 | firstLine = true; 69 | ret.set(company, arr); 70 | arr = []; 71 | return; 72 | } 73 | add(l); 74 | }); 75 | 76 | return ret; 77 | } 78 | 79 | export const logger = { 80 | info(...args: any[]) { 81 | console.log(new Date(), ...args); 82 | }, 83 | error(...args: any[]) { 84 | console.error(new Date(), ...args); 85 | }, 86 | }; 87 | -------------------------------------------------------------------------------- /static/996.ICU_03.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/X-lab2017/github-analysis-report-2019/c7e33924561c15626d0e1b3bf9e58ae118b40057/static/996.ICU_03.png -------------------------------------------------------------------------------- /static/996.ICU_full_year.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/X-lab2017/github-analysis-report-2019/c7e33924561c15626d0e1b3bf9e58ae118b40057/static/996.ICU_full_year.png -------------------------------------------------------------------------------- /static/activity_distribution_log.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/X-lab2017/github-analysis-report-2019/c7e33924561c15626d0e1b3bf9e58ae118b40057/static/activity_distribution_log.png -------------------------------------------------------------------------------- /static/activity_repo.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/X-lab2017/github-analysis-report-2019/c7e33924561c15626d0e1b3bf9e58ae118b40057/static/activity_repo.gif -------------------------------------------------------------------------------- /static/activity_user.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/X-lab2017/github-analysis-report-2019/c7e33924561c15626d0e1b3bf9e58ae118b40057/static/activity_user.gif -------------------------------------------------------------------------------- /static/china_opensource_project_language.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/X-lab2017/github-analysis-report-2019/c7e33924561c15626d0e1b3bf9e58ae118b40057/static/china_opensource_project_language.png -------------------------------------------------------------------------------- /static/chinese_top_20_act.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/X-lab2017/github-analysis-report-2019/c7e33924561c15626d0e1b3bf9e58ae118b40057/static/chinese_top_20_act.png -------------------------------------------------------------------------------- /static/company_top_act.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/X-lab2017/github-analysis-report-2019/c7e33924561c15626d0e1b3bf9e58ae118b40057/static/company_top_act.png -------------------------------------------------------------------------------- /static/global_top_10_dev_act.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/X-lab2017/github-analysis-report-2019/c7e33924561c15626d0e1b3bf9e58ae118b40057/static/global_top_10_dev_act.png -------------------------------------------------------------------------------- /static/global_top_10_dev_cnt.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/X-lab2017/github-analysis-report-2019/c7e33924561c15626d0e1b3bf9e58ae118b40057/static/global_top_10_dev_cnt.png -------------------------------------------------------------------------------- /static/global_top_10_repo_act.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/X-lab2017/github-analysis-report-2019/c7e33924561c15626d0e1b3bf9e58ae118b40057/static/global_top_10_repo_act.png -------------------------------------------------------------------------------- /static/logins_distribution_log.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/X-lab2017/github-analysis-report-2019/c7e33924561c15626d0e1b3bf9e58ae118b40057/static/logins_distribution_log.png -------------------------------------------------------------------------------- /static/tidb_10.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/X-lab2017/github-analysis-report-2019/c7e33924561c15626d0e1b3bf9e58ae118b40057/static/tidb_10.png -------------------------------------------------------------------------------- /static/tidb_full_year.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/X-lab2017/github-analysis-report-2019/c7e33924561c15626d0e1b3bf9e58ae118b40057/static/tidb_full_year.png -------------------------------------------------------------------------------- /static/tidb_network.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/X-lab2017/github-analysis-report-2019/c7e33924561c15626d0e1b3bf9e58ae118b40057/static/tidb_network.png -------------------------------------------------------------------------------- /static/vue_03.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/X-lab2017/github-analysis-report-2019/c7e33924561c15626d0e1b3bf9e58ae118b40057/static/vue_03.png -------------------------------------------------------------------------------- /static/vue_04.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/X-lab2017/github-analysis-report-2019/c7e33924561c15626d0e1b3bf9e58ae118b40057/static/vue_04.png -------------------------------------------------------------------------------- /static/vue_network.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/X-lab2017/github-analysis-report-2019/c7e33924561c15626d0e1b3bf9e58ae118b40057/static/vue_network.png -------------------------------------------------------------------------------- /static/world_active_project_language.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/X-lab2017/github-analysis-report-2019/c7e33924561c15626d0e1b3bf9e58ae118b40057/static/world_active_project_language.png -------------------------------------------------------------------------------- /static/world_participant_project_language.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/X-lab2017/github-analysis-report-2019/c7e33924561c15626d0e1b3bf9e58ae118b40057/static/world_participant_project_language.png -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compileOnSave": true, 3 | "compilerOptions": { 4 | "target": "es2017", 5 | "module": "commonjs", 6 | "strict": false, 7 | "noImplicitAny": false, 8 | "experimentalDecorators": true, 9 | "emitDecoratorMetadata": true, 10 | "charset": "utf8", 11 | "allowJs": false, 12 | "pretty": true, 13 | "noEmitOnError": false, 14 | "noUnusedLocals": true, 15 | "noUnusedParameters": true, 16 | "allowUnreachableCode": false, 17 | "allowUnusedLabels": false, 18 | "strictPropertyInitialization": false, 19 | "noFallthroughCasesInSwitch": true, 20 | "skipLibCheck": true, 21 | "skipDefaultLibCheck": true, 22 | "inlineSourceMap": true, 23 | "importHelpers": true, 24 | "esModuleInterop": true, 25 | "outDir": "lib", 26 | "sourceRoot": "src" 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /tslint.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "tslint:recommended", 3 | "rules": { 4 | "max-line-length": { 5 | "options": [ 6 | 120 7 | ] 8 | }, 9 | "new-parens": true, 10 | "no-arg": true, 11 | "quotemark": [ 12 | true, 13 | "single" 14 | ], 15 | "no-bitwise": true, 16 | "no-conditional-assignment": true, 17 | "no-consecutive-blank-lines": false, 18 | "no-console": false, 19 | "object-literal-sort-keys": false, 20 | "max-classes-per-file": false 21 | } 22 | } 23 | --------------------------------------------------------------------------------