book
归档: 娱乐 
flag
mode_edit

前段时间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

navigate_before navigate_next