在正式写程序之前让我先来看看效果:

对了,这个程序的效果就是生成一个具有你想要的“contributions in the last year”图表的html页面。
当然,html文件,而不是你在Github上面个人主页中的实际的页面。
当然,你可以通过个人努力达到效果(我之前就见过一个I 心 U,但是暂时没有找到出处),不过那需要非常努力和耐性,并且那么做的话收获更多(如果不是仅仅为了那么做而commit+push的话),所以这里介绍一个程序来实现这种方法。
接下来我将用Java来编写程序,主要分为两个步骤:

  1. 下载网页源代码
  2. 根据自己设计的字体替换网页中对应的内容

其中第二步有很多现有的工具,比如Jsoup,但是可以用正则表达式直接解决,后来我发现一个写起来比较方便的方法,因为我发现每一种颜色对应一个fill元素,所以可以直接从fill元素下手。
我把设计的字体保存在了文件picture-fonts.txt(是一个只有字符"0"和"1"的字符文件)中,并把每个字符在picture-fonts.txt中的位置保存在了position.txt中。
他们的预期效果如下:

这意味着在这里你暂时只能达到“ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789”的效果。
“contributions in the last year”列表里面一共有7行53列,为了保(tou)险(lan)这里就先不去动最后一列了。所以我们有7行52列可以用,所以这个程序将会输出最多的我们想要的结果。
程序的代码就一个,内容如下:

package fungithub;

import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map; public class FunGithub { private static Map<String, Word> wordMap = new HashMap<String, Word>();
private static int[][] picNumber = new int[1000][30]; public static void main(String[] args) {
if (args.length != 2) {
System.err.println("usage : <username> <words>");
System.exit(1);
}
solve(args[0], args[1]);
} public static void solve(String username, String words) {
words = words.toUpperCase();
try (
BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(System.getProperty("user.dir") + "/picture-fonts.txt"), "utf-8"))
) {
int idx = 0;
String line = null;
while ((line = br.readLine()) != null) {
line = line.trim();
if (line.length() == 0) continue;
int len = line.length();
char[] ch = line.toCharArray();
for (int i = 0; i < len; i ++) {
char c = ch[i];
picNumber[idx][i] = (int) c - (int)'0';
}
idx ++;
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e1) {
e1.printStackTrace();
}
try (
BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(System.getProperty("user.dir") + "/position.txt"), "utf-8"))
) {
String line = null;
while ((line = br.readLine()) != null) {
line = line.trim();
if (line.length() == 0) continue;
Word temp = new Word(line);
wordMap.put(temp.getC(), temp);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e1) {
e1.printStackTrace();
} List<Integer> allWords = new ArrayList<Integer>();
int i;
for (i = 0; i < words.length(); i ++) {
String oneWordString = String.format("%c", words.charAt(i));
Word oneWord = wordMap.get(oneWordString);
if (oneWord == null) {
System.err.println(oneWordString + " not exists!");
continue;
}
List<Integer> tmpWordsList = oneWord.getWordsList();
if (allWords.size() + tmpWordsList.size() > 52 * 7)
break;
else {
allWords.addAll(tmpWordsList);
if (allWords.size() + 7 <= 52 * 7)
for (int j = 0; j < 7; j ++)
allWords.add(0);
}
}
System.out.println("\"" + words.substring(0, i) +"\" solved!");
int delta = 52 * 7 - allWords.size();
for (int j = 0; j < delta; j ++) allWords.add(0);
// allWords -- the list with 52 * 7 words generated. // download url content
URL url = null;
HttpURLConnection urlConnection = null;
BufferedReader reader;
String pageContent = "";
try {
url = new URL("https://github.com/" + username);
urlConnection = (HttpURLConnection) url.openConnection();
reader = new BufferedReader(new InputStreamReader(urlConnection.getInputStream(), "utf-8"));
String line;
while ((line = reader.readLine()) != null){
pageContent += line + "\n";
}
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} pageContent = pageContent.replaceAll("fill=\"#[0-9a-e]{6}\"", "MoON1igHt");
for (int word : allWords) {
String fillStr = null;
if (word == 1) {
fillStr = "fill=\"#1e6823\"";
} else {
double r = Math.random();
if (r <= 0.3) fillStr = "fill=\"#eeeeee\"";
else if (r <= 0.9) fillStr = "fill=\"#d6e685\"";
else if (r <= 0.96) fillStr = "fill=\"#8cc665\"";
else fillStr = "fill=\"#44a340\"";
}
pageContent = pageContent.replaceFirst("MoON1igHt", fillStr);
}
pageContent = pageContent.replaceAll("MoON1igHt", "fill=\"#eeeeee\""); // write content to output html file, here I set it to Desktop, here I am the user "Administrator" on Windows7
String outputFileName = "C:/Users/Administrator/Desktop/" + username + "-" + words + ".html";
try (
OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream(outputFileName), "utf-8");
) {
osw.write(pageContent);
} catch (UnsupportedEncodingException | FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} System.out.println(username + "-" + words + ".html successifully generated at desktop!");
} static class Word { private String c;
private int px;
private int py;
private int height;
private int width;
private List<Integer> wordsList; public Word(String line) {
String[] arr = line.split(",");
c = arr[0];
px = Integer.parseInt(arr[1]);
py = Integer.parseInt(arr[2]);
height = Integer.parseInt(arr[3]);
width = Integer.parseInt(arr[4]); // generate wordsList
wordsList = new ArrayList<Integer>();
for (int j = 0; j < width; j ++)
for (int i = 0; i < height; i ++)
wordsList.add(picNumber[px+i][py+j]);
} public String getC() { return c; }
public int getPx() { return px; }
public int getPy() { return py; }
public int getHeight() { return height; }
public int getWidth() { return width; }
public List<Integer> getWordsList() { return wordsList; }
}
}

另外还有2个资源文件,Github项目位置:https://github.com/moonlightpoet/FunGithub 有兴趣可以玩一下。
另外github pages上面放了两个可以看看在线效果(一个I Love you的和一个Fxxk you的):

I Love You
Fxxk You

注:今天找到了知乎上问题的出处

Github恶搞之自定义你的contribution图表的更多相关文章

  1. 4.总结近5周以来的github上的工作情况,以图表方式分析你小组的工作情况、存在的问题及解决的方案。(尤心心)

    4.总结近5周以来的github上的工作情况,以图表方式分析你小组的工作情况.存在的问题及解决的方案. (1)利用github本身的graphs可以清晰的看出小组成员在github上面的交互,可以直接 ...

  2. Github 恶搞教程(一起『玩坏』自己的 Github 吧)

    最近在伯乐在线读到一篇趣文,<如何在 Github『正确』做贡献>,里面各种能人恶搞 Github 的『Public contributions』,下面截取几个小伙伴的战绩: 顺藤摸瓜,发 ...

  3. GitHub pages+自定义域名(腾讯云域名)+cloudflare加速

    本人也是第一次走完整个流程,github pages当然一直有使用,创建也很简单,并且网上教程也比较多:然后是关于自定义域名的问题,自己以前使用过国外的免费域名,然后是直接修改就ok了,然后这次使用了 ...

  4. JHChart 1.1.0 iOS图表工具库中文ReadMe

    JHChart(最新版本1.1.0) 好吧,的确当前的github上已经存有不少的iOS图表工具库,然而,当公司的项目需要图表时,几乎没有哪个第三方能够完全满足我的项目需求.无奈之下,本人不得不花费一 ...

  5. 美丽的Java图表类库

    摘要 在使用java做后台站点的开发张,图表和报表功能都是不可或缺 的.本文推荐了8款最精彩实用的Java图表应用,大部分图表应用的功能都类似,主要在于界面的美观性和使用的灵活性上有一点高低. 正文 ...

  6. 非常有用的GitHub链接

    平常开发工作中,我经常取Github上搜索项目,Clone下来学习使用,在这个过程中,发现了好多比较好的Github地址,记录下来,分享出去. image 非常有用的GitHub链接(顺序不分先后): ...

  7. Chart 图表开源项目总结

    在Android开发中,我们不免会遇到图表展示的需求,以下是本人之前star的悬浮窗的开源项目,供大家参考: 1. WilliamChart:创建图表的Android库 2. HelloCharts: ...

  8. Github使用教程(一)------ 初识Github

    上一节我们解决了Github网站响应慢,加载不完全的情况,接下来我们就要正式开始使用Github了. :好,那我先安装Git,稍后就上传项目. :......你Github网站都看懂了? :还需要看懂 ...

  9. 2019最新Android常用开源库总结(附带github链接)

    前言 收集了一些比较常见的开源库,特此记录(已收录350+).另外,本文将持续更新,大家有关于Android 优秀的开源库,也可以在下面留言. 一 .基本控件 1.TextView HTextView ...

随机推荐

  1. jquery中遍历

    1.jQuery--Dom遍历 1)jquery遍历---祖先元素 parents() 方法返回被选元素的所有祖先元素,它一路向上直到文档的根元素 (<html>).也可以使用可选参数来过 ...

  2. docker 报错: Job for docker.service failed because the control process exited with error code. See "systemctl status docker.service" and "journalctl -xe" for details.

    centos 启动docker服务报错: Job for docker.service failed because the control process exited with error cod ...

  3. 多个string数组组装成一个List<Object>

    最近遇到一个问题,数据库里面的数据存了一个多图字段和一个图片对应的排序,然后输出的时候需要按排序处理下. 当然,最容易想到的办法是遍历,然后添加,这次不想玩这么低级的代码,而且类似的需求项目中有好几个 ...

  4. python部分面试- 测试维度

    2. 软件测试的维度 1. 正确性:功能 正确 2. 健壮性: 意外的输入,不会崩溃 3. 性能: 大压力, 依然能工作 4. 可靠性: 长时间,不会崩溃 5. 易用性: 目标客户,都易用 6. 安全 ...

  5. J - 青蛙的约会(扩展欧几里得)

    https://vjudge.net/contest/218366#problem/J 第一步追及公式要写对:y+nk-(x+mk)=pL => (n-m)k+lp=x-y 可以看出扩展欧几里得 ...

  6. Wordpress添加分类

    网址一般不用中文,别名方便让网址更美观,如: xxx/category/new/

  7. puttygen 命令行 id_rsa.pub 转 ppk

    网上只有puttygen GUI程序的说明,我是linux下的环境,懒得切换到win下了,putty 也有linux版本的,不过可用软件会少点,且GUI会没win下完善. 其实 一条命令搞定: put ...

  8. redis批量删除key 远程批量删除key

    一.遇到的问题 在开发的过程中,经常会遇到要批量删除某种规则的key,如缓存的课程数据“course-课程uid”,其中课程uid是变量,我们需要删除"course-*"这一类的数 ...

  9. 朗科32G TF卡的读写测试

    卡是这样的, 下面是实际测试的结果. 容量测试 SKS的USB2外置读卡器, X240内置读卡器加上SD卡套    UNITEK的USB3.0读卡器, 经过UNITEK的USB3.0 HUB 看来读4 ...

  10. 【大话QT之十二】基于CTK Plugin Framework的插件版本号动态升级

    应用需求: 某些场景下我们可能面临这种问题,在执行着的应用程序不能终止的情况下,升级某个功能(或添,或减.或改动).在不採用CTK Plugin Framework插件系统架构的情况下这将是非常困难的 ...