论自动化武器对Luogu绘版的影响

  1. 1. Get Started
    1. 1.1. 网络请求
      1. 1.1.1. 抓包
      2. 1.1.2. 实现
    2. 1.2. 颜色拟合
      1. 1.2.1. 颜色空间
    3. 1.3. 图片
      1. 1.3.1. PPM格式
    4. 1.4. 账号切换
  2. 2. Advanced
    1. 2.1. 维护
      1. 2.1.1. 任务队列
      2. 2.1.2. 获取绘版信息
    2. 2.2. 并发
    3. 2.3. 分布式

前段时间luogu搞了个绘版活动,本着娱乐的心情写了个小脚本,写一下思路qwq

脚本地址:Github

Get Started

网络请求

抓包

我们可以直接在浏览器里按下F12,当我们点一个点时,注意到我们向服务器发送了一个POST请求,发送的数据是x='xxx' y='xxx' color='xxx'

这么来说,如果我们的程序能够定时地向luogu的服务器发请求就可以完成绘画了(先不管颜色与位置)

实现

无论是用py还是js都很容易实现,js可以使用jQuery$.post()方法,而py用户可以使用requests

颜色拟合

我们总不能做一只只会涂黑块的咸鱼吧

好心的luogu在console里打印出了颜色代码(32进制数)与rgb的对应关系

(脚本友好型绘版)

一种容易想到的方法是将rgb当成空间内某点的坐标,即该点的坐标是$(r,g,b)$

然后可以找出距离最小的一个颜色就好啦

颜色空间

但是。。由于rgb三维最近从某些意义上并不能反映最近颜色

所以一种值得推荐的方法是使用HSL颜色空间

图片

画图什么的。。总要把图读进去对吧

我们在OI中遇到的“图”大多以字符数组的形式存在

我们脑补一下,理想的图片格式应该是这样的:

第一行两个整数$h,l$,分别表示图片的高和宽

以下每行三个整数,对于第$i$行的三个整数$r,g,b$,表示第$\lfloor\frac i l\rfloor$行第$i \text{ mod }l$个像素的rgb值

不过我们常见的PNG,JPEG等格式并没有这种操作

好在有一种名叫ppm的格式适合我们

PPM格式

这种格式的描述和我描述的相差无几,除了一点:

  • ppm格式文件的除注释外的第三个整数不表示rgb值,而是表示rgb的最大分量

账号切换

总不能一个号单线程到老吧

注意到luogu使用两个cookie来标识身份

UM_IDclient_id

对于py选手,切换是很容易的,详情见requests文档

对于js选手。。emmm貌似开多个浏览器可以解决。。。

Advanced

维护

维护有多种实现,我这里介绍我xjb yy的一种

任务队列

把所有的像素点当成一个task,加入任务队列中

  • 每次从队头取出一个元素
  • 检查其是否已经被画过
  • 如果是的话就可以把这个元素扔回队尾
  • 否则发送请求
  • 然后扔到队尾

就可以了

但是。。怎么获取绘版信息呢?

获取绘版信息

我们再次打开Chrome的F12

观察到有一个叫PaintBoard的请求

点开一看,是一个字符方阵,用32进制数来表示颜色

值得注意的是$x,y$坐标是相反的

所以我们可以向这个东西发GET请求,比对一下就好啦

注意到这个方阵很大,我们可以缓存一下,画上20-30个点之后再更新

并发

至今为止我们都没有用到多线程(实际上也不是很必要)

如果你实在显得无聊的话。。可以试试。。(但是性能瓶颈大概率不在这里)

分布式

ranwen dalao的骚操作

client定时从中心服务器获取任务,然后绘制

效果拔群

最后打个广告,欢迎来东方绘版群养老,群号:691090556