# plot import matplotlib.pyplot as plt import calendar import datetime from datetime import datetime as dt import csv import seaborn as sns import pandas as pd from tqdm import tqdm # 現在の年を取得 def get_year(): currentDateTime = datetime.datetime.now() date = currentDateTime.date() year = date.strftime("%Y") return int(year) # 曜日を取得 def get_dow(day): # day of week dow = datetime.datetime.strptime(day, '%Y-%m-%d').strftime('%a') return dow # 曜日を数字で取得 def get_dow_no(dow): if (dow == "Sun"): return 0 elif (dow == "Mon"): return 1 elif (dow == "Tue"): return 2 elif (dow == "Wed"): return 3 elif (dow == "Thu"): return 4 elif (dow == "Fri"): return 5 elif (dow == "Sat"): return 6 # 月を英語の文字列で取得 def get_month_en(day): # day of week month_en = datetime.datetime.strptime(day, '%Y-%m-%d').strftime('%b') return month_en # 月が変わった(week+0.5)を取得 def get_month_change_point(year_dayslist): month_point = [] # 月が替わるタイミングのweek day_count = 0 week = 0 for month in range(12): month_point.append(week+0.5) for i in range(calendar.monthrange(int(get_year()), month+1)[1]): dow = get_dow(year_dayslist[day_count]) day_count += 1 if dow == "Sat": week += 1 return month_point # 現在の年の日数を取得 def calc_days(): year_days = 0 for i in range(12): year_days += calendar.monthrange(get_year(), i+1)[1] return year_days # 現在の年の日付をリストで取得 def get_year_dayslist(): year_dayslist = [] for month in range(12): for day in range(calendar.monthrange(int(get_year()), month+1)[1]): year_dayslist.append("{:<4d}-{:0>2d}-{:0>2d}".format(get_year(), month+1, day+1)) return year_dayslist # 現在の年のコミットデータを作成 def set_commit_calendar( year_days, year_dayslist, committed_year, committed_datetimes): f = open("./log/commit_calendar.csv","w+", encoding="utf_8_sig", newline='') csv_writer = csv.writer(f) csv_writer.writerow([ 'year', 'month', 'month_en', 'day', 'dow_no', 'dow', 'week', 'commit']) # csvヘッダー追加 day_count = 0 week = 0 # 現在の年の日ごとコミット数を計算 with tqdm(total=year_days, desc='commit_calendar.csv') as pbar: # プログレスバーの設定 for month in range(12): for day in range(calendar.monthrange(int(get_year()), month+1)[1]): commit_count = committed_datetimes.count(year_dayslist[day_count]) dow = get_dow(year_dayslist[day_count]) dow_no = get_dow_no(dow) month_en = get_month_en(year_dayslist[day_count]) # committed_year.setdefault(year_dayslist[day_count], committed_datetimes.count(year_dayslist[day_count])) csv_writer.writerow([ get_year(), month+1, month_en, day+1, dow_no, dow, week, commit_count]) # csvファイルに書き込み day_count += 1 if dow == "Sat": week += 1 pbar.update(1) # プログレスバーの進捗率を更新 f.close() # 日付差の日数を算出(リストに最終日も含めたいので、+1) def get_dayslist(committed_datetimes, sum_commits): dayslist = [] # 最初から最後のコミット間の日付リスト first_commit = committed_datetimes[int(sum_commits)-1] last_commit = committed_datetimes[0] # 日付条件の設定 strdt = dt.strptime(first_commit, '%Y-%m-%d').date() # 開始日 enddt = dt.strptime(last_commit, '%Y-%m-%d').date() # 終了日 # 日付差の日数を算出(リストに最終日も含めたいので、+1しています) days_num = (enddt - strdt).days + 1 for i in range(days_num): dayslist.append(strdt + datetime.timedelta(days=i)) # 日付差のリスト return dayslist # コミットの合計値を日付順で計算し、csvに出力 def set_commit_transition(committed_datetimes, dayslist): f = open("./log/commit_transition.csv","w+", encoding="utf_8_sig", newline='') csv_writer = csv.writer(f) csv_writer.writerow([ 'day', 'commit', 'sum commit']) # csvヘッダー追加 day_commitlist = [] sum_commitlist = [] sum_commit = 0 # 現在の年の日ごとコミット数を計算 with tqdm(total=len(dayslist), desc='commit_transition.csv') as pbar: # プログレスバーの設定 for day in dayslist: # コミットの合計値を日付順で計算 day_commits = committed_datetimes.count(str(day)) day_commitlist.append(day_commits) sum_commit += day_commits sum_commitlist.append(sum_commit) csv_writer.writerow([ day, day_commits, sum_commit]) # csvファイルに書き込み pbar.update(1) # プログレスバーの進捗率を更新 f.close() return day_commitlist, sum_commitlist def run(repo): # ------------ # --- fig2 --- # ------------ sum_commits = repo.git.rev_list('--count', 'HEAD') # コミットの総数 # コミット履歴を取得 committed_datetimes = [] # コミットした日付リスト for commit in repo.iter_commits(): committed_datetimes.append(commit.committed_datetime.strftime('%Y-%m-%d')) dayslist = get_dayslist(committed_datetimes, sum_commits) # 日付差の日数を算出 day_commitlist, sum_commitlist = set_commit_transition(committed_datetimes, dayslist) # コミットの合計値を日付順で計算 # ------------ # --- fig1 --- # ------------ year_days = calc_days() # 現在の年の日数 year_dayslist = get_year_dayslist() # 現在の年の日付リスト committed_year = {} # 現在の年の日ごとコミット数 mcp = get_month_change_point(year_dayslist) # 月が変わった(week+0.5)を取得 # コミットデータを作成 set_commit_calendar(year_days, year_dayslist, committed_year, committed_datetimes) # ------------ # --- plot --- # ------------ # --- fig1 --- # CSV読み込み df1 = pd.read_csv("./log/commit_calendar.csv",sep=",") df1.columns = ['year','month','month_en','day','dow_no','dow', 'week', 'commit'] df1 = df1.pivot('dow_no','week','commit') fig1, ax1 = plt.subplots(figsize=(10, 3)) # 10対3のプロットを作成 sns.heatmap( df1, cmap="Greens", linewidths=.25, square=True, cbar=False) ax1.set_title(str(get_year()) + " year (" + repo.git.rev_list('--count', 'HEAD') + " commit)") ax1.set_xlabel('') ax1.set_ylabel('') ax1.set_yticks([1.5, 3.5, 5.5]) ax1.set_yticklabels(['Mon', 'Wed', 'Fri'], rotation=0) ax1.set_xticks([mcp[0], mcp[1], mcp[2], mcp[3], mcp[4], mcp[5], mcp[6], mcp[7], mcp[8], mcp[9], mcp[10], mcp[11]]) ax1.set_xticklabels(['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'], rotation=0) fig1.savefig("pic/commit_calendar.png", tight_layout=True) # グラフを画像で保存 # --- fig2 --- fig2, ax2 = plt.subplots(figsize=(12, 7)) ax2.plot(dayslist, sum_commitlist, label="sum", linestyle="-", marker="", color="lightseagreen") ax2.plot(dayslist, day_commitlist, label="1day", linestyle="-", marker="", color="lightcoral") ax2.grid(b=True, which='major', color='gray', linestyle='-', linewidth=0.5, alpha=0.3) ax2.minorticks_on() ax2.spines['right'].set_visible(False) ax2.spines['top'].set_visible(False) ax2.spines['bottom'].set_visible(False) ax2.spines['left'].set_visible(False) ax2.set_title("commit transition") ax2.set_xlabel('date') ax2.xaxis.set_tick_params(rotation=10) ax2.set_ylabel('commits') ax2.legend() ax2.fill_between(dayslist, 0, day_commitlist, facecolor='lightcoral', alpha=0.3) ax2.fill_between(dayslist, day_commitlist, sum_commitlist, facecolor='lightseagreen', alpha=0.3) fig2.savefig("pic/commit_transition.png")