阅读视图

发现新文章,点击刷新页面。
☑️ ⭐

使用原生JS实现Echarts数据导出Excel的功能

Echarts toolbox 增加数据导出Excel的功能

Echarts的toolbox提供了很多工具,例如saveAsImage(导出图片)、magicType(切换类型)等,具体的可以参考toolbox官方文档。toolbox原生提供的功能算是比较全面的了,但唯独缺少了一键将数据导出为Excel的功能。虽然可以通过toolbox中的dataView(数据视图)查看数据,然后复制粘贴到Excel中,但这种做法着实不够优雅。好在toolbox支持用户自定义工具。

在自定义功能之前,需要注意的是,自定义的工具名字,只能以my开头,例如myTool1、myTool2......,具体示例可以参考toolbox.feature文档,示例代码如下:

toolbox: {
    feature: {
        myTool1: {
            show: true,
            title: '自定义扩展方法1',
            icon: 'path://M432.45,595.444c0,2.177-4.661,6.82-11.305,6.82c-6.475,0-11.306-4.567-11.306-6.82s4.852-6.812,11.306-6.812C427.841,588.632,432.452,593.191,432.45,595.444L432.45,595.444z M421.155,589.876c-3.009,0-5.448,2.495-5.448,5.572s2.439,5.572,5.448,5.572c3.01,0,5.449-2.495,5.449-5.572C426.604,592.371,424.165,589.876,421.155,589.876L421.155,589.876z M421.146,591.891c-1.916,0-3.47,1.589-3.47,3.549c0,1.959,1.554,3.548,3.47,3.548s3.469-1.589,3.469-3.548C424.614,593.479,423.062,591.891,421.146,591.891L421.146,591.891zM421.146,591.891',
            onclick: function () {
                alert('myToolHandler1')
            }
        }
    }
}

其中的重点就是onclick函数,我希望实现点击按钮自动下载Excel的功能,下面我先给出最终实现的代码:

myTool: {
    show: true,
    title: '导出EXCEL',
    icon: 'path://M925.248 356.928l-258.176-258.176a64 64 0 0 0-45.248-18.752H144a64 64 0 0 0-64 64v736a64 64 0 0 0 64 64h736a64 64 0 0 0 64-64V402.176a64 64 0 0 0-18.752-45.248zM288 144h192V256H288V144z m448 736H288V736h448v144z m144 0H800V704a32 32 0 0 0-32-32H256a32 32 0 0 0-32 32v176H144v-736H224V288a32 32 0 0 0 32 32h256a32 32 0 0 0 32-32V144h77.824l258.176 258.176V880z',
    onclick: function(opt) {
        opt = opt.option;
        var cell, csv, csvContent, encodedUri, head, i, j, k, len, line, lines, link, ref, s, tr, tr_list, value, x, y;
        x = opt.xAxis[0].data
        y = [
            (function() {
                var k, len, ref, results;
                ref = opt.series;
                results = [];
                for (k = 0, len=ref.length; k < len; k++) {
                    i = ref[k];
                    results.push(i.name)
                }
                return results;
            })()
        ];
        y[0].splice(0, 0, "日期");
        value = [
            (function() {
                var k, len, ref, results;
                ref = opt.series;
                results = [];
                for (k=0, len = ref.length; k < len; k++) {
                    i = ref[k];
                    results.push(i.data);
                }
                return results;
            })()
        ][0];
        tr = "";
        csvContent = "data:text/csv;charset=utf-8,%EF%BB%BF";
        csv = y[0].join(",") + ",\n";
        head = "<tr>";
        ref = y[0];
        for (k = 0, len = ref.length; k < len; k++) {
            i = ref[k];
            head += '<th>' + i + '</th>';
        }
        head += "</tr>";
        tr_list = [];
        i = 0;
        lines = [];
        while (i < value[0].length) {
            j = 0;
            tr = "";
            tr += "<tr>";
            tr += "<td>" + x[i].replace(/,/g, " ") + "</td>";
            line = x[i].replace(/,/g, ' ');
            while (j < value.length) {
                cell = value[j][i];
                tr += "<td>" + cell + "</td>";
                line += ", " + cell;
                j += 1;
            }
            line += "\n";
            tr += "</tr>";
            i += 1;
            lines.push(line);
            tr_list.push(tr);
        }
        csv += lines.join("");
        encodedUri = csvContent + encodeURI(csv);
        var downloadLink = document.createElement('a');
        // 设置<a>元素的属性
        downloadLink.href = encodedUri;
        downloadLink.target = '_blank'; // 在新窗口中打开下载
        downloadLink.download = '气井分类.csv'; // 设置下载文件的名称
        // 将<a>元素添加到文档中
        document.body.appendChild(downloadLink);
        // 触发<a>元素的点击事件,开始下载
        downloadLink.click();
        // 下载完成后,从文档中移除<a>元素
        document.body.removeChild(downloadLink);
    }
}

从上往下看比较重要的几个参数,icon顾名思义就是按钮的图标,我从阿里巴巴矢量图标库中选择了一个类似于"保存"的图标。onclick函数可以传参数,这个参数具体代表什么我也不太清楚,在函数里log打印看看就清楚了,我个人觉得大概是类似于this之类的东西,里面保存了这个echarts对象的很多信息,其中就有完整的数据信息。csvContent设置的是保存文件的类型,我保存的csv格式的文件,类型名和文件后缀名必须对应上,否则就会出问题。常见的文件类型可以看MIME类型列表。其实大体设计思路就是将数据编码为HTML的表格(前端不会展示该表格),最终下载这个表格,<th>包裹的是最终导出Excel文件中每一列的列名。一个<tr>中是一种类别的数据,<tr>中一般来说会有很多<td>,每个<td>包裹的就是具体属于该类的每一个样本。我的数据如下图所示:

导出的csv如下所示:

后记

其实在网上搜Echarts导出Excel字样,有很多大佬给出了解决方案,有些是用了第三方库,有些是基于Vue的,但是由于笔者并不会Vue,并且某些第三方库可能会和我本身的项目冲突,因此我才想着能否使用原生JS解决,不过由于我的JS水平也就属于半吊子,所以我自己写不出来,翻遍了搜索引擎也没找到用原生JS实现的代码。后来我是在Echarts的Github Issues中翻到了一位大佬的提问,从他的提问代码中窥探到了答案,在这里贴出这个Issue,并且感谢下这位大佬

☑️ ☆

亚马逊实时 AI 编程助手 CodeWhisperer使用体验

1. 什么是CodeWhisperer ?

最近ChatGPT展现出强大AI能力给我们带来了深刻的影响,AI现在不是一个概念,基于AI的产品一定在各行各业帮助工作人员更快更好的完成繁琐的复杂的任务,提升工作效率,而在AI技术的发源地也就是码农圈,也早已经出现了一些好用的AI驱动的编程助手,这些助手可以在IDE中为我们补全代码甚至按照注释自动编写代码,基于AI技术,这些编程助手吸收了Github公开代码库和一些可公开代码库的数据样本,提供自动补全,语法检查、错误修复、导航跳转、类型与范围提示、参数补全、自动注释、代码生成、代码质量分析,漏洞检测等等功能。参与亚马逊云科技云创计划即可免费体验各种云服务

AWS 2023/4月已正式推出Amazon CodeWhisperer,是亚马逊的用几十亿行开源代码训练出来的 AI 工具,它可以根据你的代码注释和现有代码实时生成代码建议。其中CodeWhisperer个人套餐,所有开发人员均可免费使用。

Amazon CodeWhisperer目前支持多种语言(Python, Java, JavaScript, TypeScript, C#, Go, Rust, PHP, Ruby, Kotlin, C, C++, Shell scripting, SQL, and Scala);并同时支持多种IDE(JetBrains IDEs, Visual Studio (VS) Code, AWS Cloud9, AWS Lambda console)

2. 试用

我们以VS Code为例来做一个简单的体验

首先是安装VS Code插件,AWS Toolkit是亚马逊云科技官方产品,现在集成了CodeWhisperer

安装好了后,我们直接点击AWS Toolkit,并找到下面的CodeWhisperer,这是我们接着点击run,启动CodeWhisperer

然后我们注册或者登录AWS Builder ID

当出现如图的绿色的提示就代表完成

3. 上手体验

当我们写完后,我们简单的测试下,发现结果是正确的,此外我们还可以进行代码安全扫描和代码来源检查

当然无论你多么信任CodeWhisperer或者其他的AI辅助工具,你都需要人工检查代码正确性并做好单元测试,AI辅助工具主要是减少你在互联网上搜索或者查看文档的时间,至于代码的正确性和效率,需要你来核对

☑️ ☆

2023总结

2023对我来说是改变非常巨大的一年,首先从身份的转变上,这一年我终于结束了我的求学生涯,正式从学生变成了一名打工人。“读了20几年书,以后终于不用再读书了”,快要毕业的时候我总是这么想着,以为即将脱离苦海,但其实无非是从一个苦海跳到另一个苦海罢了。接着从财富上来说,工作意味着有了稳定的收入来源,终于可以自己想买什么就买什么,由于我是果粉,并且极度讨厌华为(如果看到这里你产生了某些心理上的不适,请退出这篇文章),因此10月一发工资我就果断入手了iphone 15 pro,同时给自己买了一份保险,每年9000块钱,年底在小县城看上了一套二手房,付了1.5w的购房订金,除此之外还海淘了不少中古游戏,以及各类奇奇怪怪的电子产品,前前后后加起来又花了1w左右。本来到这儿几乎快把我上4个月班的工资花光了,但是年底发了一笔年终奖,又给我回了口血

今年是我代码能力提升最快的一年,实际上直到上班之前我都好久没写过稍微复杂的代码了。我入职的单位并不是互联网公司,同事也几乎没有计算机专业的,不过领导非常赏识我,希望我能发挥所长,利用编程来解决问题,我非常感谢部门领导,可以说他对我有知遇之恩。入职之后我写过爬虫、Excel数据处理、Flask+Layui+JS网站搭建、Windows桌面应用程序自动化等,详情可以查看我的这期视频。可以说除了爬虫和Excel数据处理是我以前接触过的,剩下的全是从零开始学,但是为了快速解决问题,实际上也没有那么多时间真的让你从头学起,无非就是点开API文档快速看一下示例,然后一点一点Debug把功能实现。说实话,我非常享受这种极限编程的感觉,快速学会一个库的核心功能,快速上手,快速Debug,中间不会的快速查资料解决,以达到短时间完成工作的效果,这非常有挑战性也很有成就感,尤其是同事在使用时对你表示由衷的赞叹,每每这时我都会觉得:“计算机真是学对了,计算机就是世界第一专业!”

今年是我特别注重健康的一年,可能让大家很讶异的是,我略微有点酒瘾,尤其喜欢喝啤酒,我非常享受那种微醺的感觉。但是今年无论是家庭聚餐,还是在外和同学、同事吃饭,一年总共也就喝了不超过500ml的啤酒,除了谢师宴喝了一点白酒,剩下的时间几乎是滴酒不沾。往大了说酒精是一类致癌物,往小了说,在代谢酒精的过程中,会消耗体内大量的维生素,时间长了还会导致酒精肝、痛风等等,因此在23年年初我就定下了目标:要戒酒。回顾这一年,这一目标也算是达成了。除了戒酒以外,几乎每天我都有吃各种各样的补剂,例如复合维生素、益生菌、鱼油等等,因为我比较挑食,具体来说我只喜欢吃肉,不爱吃素,这就导致我的营养摄入不均衡,因此我才选择额外摄入一些营养补剂

今年是充满遗憾的一年,每当学术界有什么爆炸性的新闻时,我总会想:“要是我当初选择读博就好了”,我对计算机领域内的所有事情仍然保持着最大的好奇,我也曾不止一次的想紧跟学术前沿,可是最后却发现实在没那个精力,就拿今年比较火的文生图为例,我甚至从来没有亲自生成过一张图片,一方面是我实在懒得去研究如何部署模型,另一方面是我不知道该生成什么图片,于是也就懒得去找在线Demo,就好像大部分人第一次使用ChatGPT时不知道该说些什么,也就只能试探性的发送:“你好”便作罢了。今年同样有很多事情出乎我的意料,不过涉及到隐私,解释起来比较复杂,也就不在此赘述了

总的来说,今年对我来说有很特别的意义,我毕业了、将自己剩下半辈子的人生埋葬在了一家公司、即将拥有属于自己的房子。我对自己24年的期望是,B站达到1w粉、去日本旅游、尽量别再刚愎自用

☑️ ☆

Flooding-X: 超参数无关的Flooding方法

ICML2020的论文《Do We Need Zero Training Loss After Achieving Zero Training Error?》提出了一种Flooding方法,用于缓解模型过拟合,详情可以看我的文章《我们真的需要把训练集的损失降到零吗?》。这里简单过一下,论文提出了一个超参数$b$,并将损失函数改写为

$$ \tilde{\mathcal{L}}(\boldsymbol{\theta}) = |\mathcal{L}(\boldsymbol{\theta}) -b| + b\tag{1} $$

其中,$b$是预先设定的阈值,当$\mathcal{L}(\boldsymbol{\theta})>b$时$\tilde{\mathcal{L}}(\boldsymbol{\theta})=\mathcal{L}(\boldsymbol{\theta})$,这时就是执行普通的梯度下降;而$\mathcal{L}(\boldsymbol{\theta})<b$时$\tilde{\mathcal{L}}(\boldsymbol{\theta})=2b-\mathcal{L}(\boldsymbol{\theta})$,注意到损失函数变号了,所以这时候是梯度上升。因此,总的来说就是以$b$为阈值,低于阈值时反而希望损失函数变大。论文把这个改动称为"Flooding"

这样做有什么效果呢?论文显示,在某些任务中,训练集的损失函数经过这样处理后,验证集的损失能出现 "二次下降(Double Descent)",如下图


左图:不加Flooding的训练示意图;右图:加了Flooding的训练示意图

我们可以假设梯度先下降一步后上升一步,学习率为$\varepsilon$,通过泰勒展开可以得到

$$ \boldsymbol{\theta}_{n+1} \approx \boldsymbol{\theta}_{n-1}-\frac{\varepsilon^2}{2}\nabla_{\boldsymbol{\theta}} ||g(\boldsymbol{\theta}_{n-1})||^2\tag{2} $$

其中,$\boldsymbol{\theta}_{n}$表示第$n$次迭代的参数,$g(\boldsymbol{\theta}_{n-1})=\nabla_{\boldsymbol{\theta}}\mathcal{L}(\boldsymbol{\theta}_{n-1})$表示损失对参数$\boldsymbol{\theta}_{n-1}$的梯度。式(2)的结果相当于以$\frac{\varepsilon^2}{2}$为学习率、损失函数为梯度惩罚$|g(\boldsymbol{\theta})||^2=||\nabla_{\boldsymbol{\theta}}\mathcal{L}(\boldsymbol{\theta})||^2$的梯度下降

详细的推导过程见《我们真的需要把训练集的损失降到零吗?》

Achilles' Heel of Flooding

Flooding的阿喀琉斯之踵在于超参数$b$,我们需要花非常多的时间寻找最佳的阈值$b$,这并不是一件容易的事

Achilles' Heel(阿喀琉斯之踵)阿喀琉斯是古希腊神话故事中的英雄人物,刀枪不入,唯一的弱点是脚后跟(踵)。后用于来比喻某东西的致命缺陷

下图展示了使用BERT在SST-2数据集上不同的阈值$b$对结果的影响(黄色区域是最佳结果)。可以看出,$b$的设置对结果的影响非常大

Gradient Accordance

ACL2022的投稿有一篇名为《Flooding-X: Improving BERT’s Resistance to Adversarial Attacks via Loss-Restricted Fine-Tuning》的文章,以"梯度一致性"作为开启Flooding的"阀门",而不再采用超参数$b$。具体来说,我们首先定义包含参数$\boldsymbol{\theta}$的模型$f$,考虑一个样本$x$以及真实标签$y$,它们的损失为$\mathcal{L}(f(\boldsymbol{\theta}, x), y)$,损失关于参数的梯度为

$$ \boldsymbol{g} = \nabla_{\boldsymbol{\theta}}\mathcal{L}(f(\boldsymbol{\theta}, x),y)\tag{3} $$

其中,式(3)的负值就是参数$\boldsymbol{\theta}$更新的方向。现在我们考虑两个样本$(x_1,y_1), (x_2,y_2)$的情况,根据上述定义,样本1的梯度为

$$ \boldsymbol{g_1} = \nabla_{\boldsymbol{\theta}}\mathcal{L}(f(\boldsymbol{\theta}, x_1), y_1)\tag{4} $$

对于样本1来说,参数更新所导致的损失变化为

$$ \begin{aligned} \Delta \mathcal{L}_1 = &\mathcal{L}(f(\boldsymbol{\theta} - \varepsilon \boldsymbol{g_1}, x_1), y_1)\\ &- \mathcal{L}(f(\boldsymbol{\theta}, x_1), y_1) \end{aligned}\tag{5} $$

将$f(\boldsymbol{\theta}, x_1)$通过泰勒展开变形得

$$ f(\boldsymbol{\theta}, x_1)\approx f(\boldsymbol{\theta} - \varepsilon\boldsymbol{g_1}, x_1) + \varepsilon \boldsymbol{g_1}\frac{\partial f}{\partial \boldsymbol{\theta}}\tag{6} $$

$$ \frac{f(\boldsymbol{\theta} - \varepsilon\boldsymbol{g_1}, x_1) -f(\boldsymbol{\theta}, x_1)}{\varepsilon \boldsymbol{g_1}}= \frac{\partial f}{\partial \boldsymbol{\theta}} $$

我们将$\varepsilon \boldsymbol{g_1}\frac{\partial f}{\partial \boldsymbol{\theta}}$记作$T(x_1)$,并对$\mathcal{L}(f(\boldsymbol{\theta}, x_1), y_1)$做类似的泰勒展开得

$$ \begin{aligned} \mathcal{L}(&f(\boldsymbol{\theta}, x_1), y_1)\\ &= \mathcal{L}(f(\boldsymbol{\theta} - \varepsilon \boldsymbol{g_1}, x_1) + T(x_1), y_1)\\ &\approx \mathcal{L}(f(\boldsymbol{\theta} - \varepsilon \boldsymbol{g_1}, x_1), y_1)\\ &+\frac{\partial \mathcal{L}}{\partial f}T(x_1) \end{aligned}\tag{7} $$

根据式(6)可以推出第一个等号,约等于是从泰勒展开推导的,具体来说

$$ \frac{\mathcal{L}(A + T(x_1), y_1) -\mathcal{L}(A, y_1)}{T(x_1)} = \mathcal{L}' $$

将式(7)带入式(5)得

$$ \begin{aligned} \Delta \mathcal{L}_1 &\approx -\frac{\partial \mathcal{L}}{\partial f}T(x_1)\\ &=-\varepsilon \boldsymbol{g_1}\frac{\partial \mathcal{L}}{\partial f} \frac{\partial f}{\partial \boldsymbol{\theta}}\\ &=-\varepsilon \boldsymbol{g_1} \cdot \boldsymbol{g_1} \end{aligned}\tag{8} $$

类似的,参数根据样本$(x_1,y_1)$更新后,在样本$(x_2, y_2)$上的损失差为$\Delta \mathcal{L}_2 = -\varepsilon \boldsymbol{g_1}\cdot \boldsymbol{g_2}$

值得注意的是,根据定义,$\Delta \mathcal{L}_1$是负的,因为模型是对于$(x_1,y_1)$更新的,自然就会导致其损失的降低。如果$\Delta \mathcal{L_2}$也是负的,那么在$(x_1, y_1)$上更新的模型被认为对$(x_2, y_2)$有积极的影响。上面的等式表明,这种共同关系相当于两个样本的梯度$\boldsymbol{g_1},\boldsymbol{g_2}$之间的乘积,我们称其为梯度一致性(Gradient Accordance)

Coarse-Grained Gradient Accordance

上面提到的可以看作是样本级别的梯度一致性,由于其粒度太细,计算起来非常复杂,因此我们将其应用到batch级别的粗粒度上进行计算

考虑训练过程中包含$n$个样本的mini-batch $B_0$,其中样本$\boldsymbol{X} = \{x_1, x_2,...,x_n\}$,标签$\boldsymbol{y}=\{y_1, y_2,...,y_n\}$,其中$y_i\in \{c_1, c_2,...,c_k\}$,即有$k$个类别。这些样本可以根据它们的标签拆分成$k$组(每组内的样本标签是一样的)

$$ \boldsymbol{X} = \boldsymbol{X_1}\cup \boldsymbol{X_2} \cup \cdots \cup \boldsymbol{X_k} $$

由此可以将$B_0$拆分成多个子batch的并集,$B_0 = B_0^1\cup B_0^2\cup \cdots B_0^k$。我们定义两个子batch $B_0^1$和$B_0^2$的类一致性分数为

$$ C(B_0^1, B_0^2) = \mathbb{E}[\cos (\boldsymbol{g_1}, \boldsymbol{g_2})]\tag{9} $$

其中,$\boldsymbol{g}_1$是模型在样本集$B_0^1$上的损失对参数的梯度,$\cos(\boldsymbol{g_1}, \boldsymbol{g_2})=(\boldsymbol{g_1}/|\boldsymbol{g_1}|)\cdot (\boldsymbol{g_2}/|\boldsymbol{g_2}|)$

类一致性可以用于判断:对类别$c_1$的样本集$B_0^1$进行梯度下降是否也会减少类别$c_2$所对应的样本集$B_0^2$的损失

假设一个Epoch中有$N$个batch,那么$B_s$与$B_t$的批一致性分数定义如下:

$$ \begin{aligned} S_{\text{batch accd}}&(B_s, B_t)\\ &=\frac{1}{k(k-1)}\sum_{j=1}^k\sum_{i=1 \atop i \neq j}^k C(B_s^i, B_t^j) \end{aligned}\tag{10} $$

批一致性可以通过评估一个批次的参数更新对另一个批次的影响,量化两个批次的学习一致性。更具体地说,$S_{\text{batch accd}}$如果是正的,表示这两个批次处于相同的学习节奏下,每个批次更新的模型对它们都有好处

任意一个Epoch的梯度一致性最终定义为

$$ \begin{aligned} &S_{\text{epoch accd}} \\ &= \frac{1}{N(N-1)}\sum_{j=i+1}^N \sum_{i=1}^{N-1} S_{\text{batch accd}}(B_s, B_t) \end{aligned}\tag{11} $$

Analysis and Discussion

实验结果这里就不放了,简单说一下就是作者使用了TextFooler、BERT-Attack、TextBugger三种攻击手段,以PGD、FreeLB、TAVAT等方法为Baseline进行对比,结果表明使用Flooding-X效果很好

从下图可以看出,当梯度一致性指标从负数变为正数时,测试集损失也开始上升,说明梯度一致性这个指标可以很好的当作是过拟合的信号

个人总结

2020年提出的Flooding本身就是一个非常有意思的Trick,可惜原论文作者也苦于超参数$b$的选择,因此其应用不算广泛。ACL2022这篇论文提出了梯度一致性的概念,让模型自己感知什么时候该进行Flooding,避免了超参数的选择问题

References

☑️ ☆

Amazon Aurora MySQL 和 Amazon RDS for MySQL 集群故障转移和只读实例扩容时间测试

1 测试背景

Amazon Aurora MySQL 是与 MySQL 兼容的关系数据库,专为云而打造,性能和可用性与商用数据库相当,成本只有其 1/10。

Amazon RDS for MySQL 让您能够在云中更轻松设置、操作和扩展 MySQL 部署。借助 Amazon RDS,您可以在几分钟内部署可扩展的 MySQL 服务器。参与亚马逊云科技云创计划即可免费体验各种云服务。云服务器12个月免费、虚拟服务器VPS 3个月免费、无服务器计算服务永久免费,更多详情请进入官网查看。

客户在使用亚马逊云科技托管 MySQL 数据库服务时,通常需要选择 Amazon Aurora MySQL 或 Amazon RDS for MySQL。本次测试是对比 Amazon Aurora MySQL 和 Amazon RDS for MySQL 在不同模式、不同机型、有无工作负载情况下的集群故障转移时间和只读实例扩容时间,为客户在亚马逊云科技上选择托管 MySQL 数据库服务提供参考。

2 测试环境

被测服务Amazon Auron MySQL和Amazon RDS for MySQL
测试区域孟买区域(ap-south-1)
测试版本Amazon Aurora 2.11.2 (MySQL 5.7)
Amazon RDS for MySQL 5.7.41
测试机型AmazonAuroraMySQLdb.r5.2xlarge和db.r5.xlarge
Amazon RDS for MySQL db.m5.4xlarge # db.m5.2xlarge
部署模式AmazonAuroraMysQL采用跨AZ部署,一写一读和一写二读两种模式
AmazonRDSforMysQL采用Multi-AZ实例部署,一写一读和一写二读两种模式
压测实例c5.12xlarge*1
压测软件sysbench (https://github.com/akopytov/sysbench)

3 测试前提

本次测试基于以下 3 个前提:

  • 压测实例、Amazon Aurora MySQL 和 Amazon RDS for MySQL 均在一个 VPC
  • Amazon Aurora MySQL 和 Amazon RDS for MySQL 均使用生产模板的默认配置
  • 开启 Amazon CloudTrail 分别统计集群故障转移和只读实例扩容的开始、结束时间

4 测试架构图

4.1 Amazon Aurora MySQL 测试架构图

4.2 Amazon RDS for MySQL 测试架构图

5 测试用例

5.1 集群故障转移时间测试用例,测试基于以下8种配置模式,分别测试无法工作负载和有工作负载两种情况下的集群故障转移时间

*工作负载场景:数据库存储100GB数据,主节点80%CPU工作负载

5.2 只读实例扩容时间测试用例,测试基于以下 8 种配置模式,分别测试无工作负载和有工作负载两种情况下的只读实例扩容时间

*工作负载场景:数据库存储 100GB 数据,主节点 80%CPU 工作负载

6 测试方法

6.1 集群故障转移时间测试方法

1.对于Amazon Aurora MySQL,在控制台上,选择目标集群的写入实例并点击下图中的“故障转移”按钮:

2.点击“日志和时间”,在下方的近期时间里查看故障转移开始和结束时间,计算出故障转移花费的时间:

3.对于 Amazon RDS for MySQL,在控制台上,选择目标集群的主实例并点击下图中的“重启”按钮,在下一个页面勾选“是否进行重启和故障转移”,点击确认:

4.点击“日志和事件”,在下方的近期事件里查看故障转移开始和结束时间,计算得出故障转移花费的时间:

5.在模拟工作负载的场景下重新统计时间,模拟工作负载的步骤如下:

sysbench /usr/share/sysbench/tests/include/oltp_legacy/oltp.lua --threads=64 --mysql-host=bench-test.cluster-cum78jhrtci1.ap-south-1.rds.amazonaws.com --mysql-user=admin --mysql-password=xxxx --mysql-port=3306 --mysql-db= bench _test --oltp-tables-count=100 --oltp-table-size=5000000 --db-driver=mysql prepare
  • 按照如下命令,对主节点进行压力测试
sysbench /usr/share/sysbench/tests/include/oltp_legacy/oltp.lua --mysql-host=bench-test.cluster-cum78jhrtci1.ap-south-1.rds.amazonaws.com --mysql-user=admin --mysql-password=xxxx --mysql-port=3306  --mysql-db= bench_test --max-requests=0 --oltp-simple-ranges=0 --oltp-distxinct-ranges=0 --oltp-sum-ranges=0 --oltp-order-ranges=0 --time=3600 --oltp-read-only=on --threads=120 run #可以通过调整 threads 来控制工作负载,不同数据库实例类型线程数不一样

6.2 只读实例扩容时间测试方法

1.对于 Amazon Aurora MySQL,在控制台上,选择目标集群并点击下图中的“添加读取器”按钮:

2.使用 CloudTrail 里 CreateDBInstance 事件的时间作为添加只读实例的开始时间:

3.回到控制台,在目标集群 “日志和事件”里使用最后一步的时间作为添加只读实例的结束时间:

4.对于 Amazon RDS for MySQL,在控制台上,选择目标集群并点击下图中的“创建只读副本”按钮:

5.使用 CloudTrail 里 CreateDBInstanceReadReplica 事件的时间作为添加只读实例的开始时间:

6.回到控制台,在目标集群“日志和事件”里使用最后一步的时间作为添加只读实例的结束时间:

7.在模拟工作负载场景下重新统计时间,模拟工作负载步骤如下:

sysbench /usr/share/sysbench/tests/include/oltp_legacy/oltp.lua --threads=64 --mysql-host=bench-test.cluster-cum78jhrtci1.ap-south-1.rds.amazonaws.com --mysql-user=admin --mysql-password=xxxx --mysql-port=3306 --mysql-db= bench _test --oltp-tables-count=100 --oltp-table-size=5000000 --db-driver=mysql prepare
  • 按照如下命令,对主节点进行压力测试
sysbench /usr/share/sysbench/tests/include/oltp_legacy/oltp.lua --mysql-host=bench-test.cluster-cum78jhrtci1.ap-south-1.rds.amazonaws.com --mysql-user=admin --mysql-password=xxxx --mysql-port=3306  --mysql-db= bench_test --max-requests=0 --oltp-simple-ranges=0 --oltp-distxinct-ranges=0 --oltp-sum-ranges=0 --oltp-order-ranges=0 --time=3600 --oltp-read-only=on --threads=120 run #可以通过调整threads来控制工作负载,不同数据库实例类型线程数不一样

7 测试数据

7.1 集群故障转移时间测试数据

表格记录时间均为 3 次测试的平均时间

7.2 只读实例扩容时间测试数据

表格记录时间均为 3 次测试的平均时间

8 测试结论

  1. Amazon Aurora MySQL 的集群故障转移时间与读写模式、实例机型、工作负载相关性较小,整体时间分布在 29 秒-41 秒之间。Amazon RDS for MySQL 的集群故障转移时间与读写模式、实例机型相关性较小,与工作负载相关性较大,在无工作负载时为 50 秒-65 秒,有工作负载时增加至 85 秒-93 秒,有工作负载的情况下故障转移时间变长。
  2. Amazon Aurora MySQL 的只读实例扩容时间与读写模式,实例机型、工作负载相关性较小,整体时间分布在 6 分 08 秒-6 分 57 秒之间。Amazon RDS for MySQL 的只读实例扩容时间与读写模式,实例机型相关性较小,与工作负载相关性较大,在无工作负载时为 6 分 12 秒-7 分 1 秒,有工作负载时增加至 15 分 19 秒-15 分 31 秒,有工作负载的情况下只读实例扩容时间变长。
  3. 对比 Amazon Aurora MySQL 和 Amazon RDS for MySQL

    1. 在无工作负载的情况下,Amazon Aurora MySQL 集群故障转移时间为 Amazon RDS for MySQL 的 64%,Amazon Aurora MySQL 集群故障转移时间更短。
    2. 在无工作负载的情况下,Amazon Aurora MySQL 的只读实例扩容时间为 Amazon RDS for MySQL 的 96%,两者相差较小。
    3. 在有工作负载的情况下,Amazon Aurora MySQL 集群故障转移时间为 Amazon RDS for MySQL 的 33%,Amazon Aurora MySQL 集群故障转移时间更短。
    4. 在有工作负载的情况下,Amazon Aurora MySQL 的只读实例扩容时间为 Amazon RDS for MySQL 的 42% ,Amazon Aurora MySQL 只读实例扩容时间更短。

综上所述,Amazon Aurora MySQL 无论是在集群故障转移时间还是只读实例扩容时间都优于 Amazon RDS for MySQL。

转自亚马逊云科技

☑️ ☆

《三角战略》:日式欧洲中世纪舞台剧

"这游戏到底会以怎样的方式结束?"这是我在游玩《三角战略》过程中经常会思考的问题;"难道就没有一种能让大家都幸福的方法吗?"这是我在游玩《三角战略》过程中一直萦绕在脑海的一句话;"我要赌上所有的一切,开辟属于自己的道路!"这是我在游玩《三角战略》过程中每次进行抉择时的想法

《三角战略》的故事舞台为战乱的诺泽利亚大陆,在曾经为了争夺盐铁利益爆发"盐铁大战"的这片大陆上,占有盐权、以女神教义为核心的沙漠国度「圣海桑德大教国」(后简称「教国」);呈现不同的政治体制及特色、重视实力、自由及铁器技术,位于北方雪地的「艾斯弗斯特公国」(后简称「公国」)与重视血统的「格林堡王国」(后简称「王国」)维持著三强鼎立的状态。战争结束后,怀着对这场源于利益垄断的战争的反思,不从属于任何国家的中立组织「诺泽利亚商会」成立了。透过平等交易盐和铁,为复兴诺泽利亚作出了一份贡献。然而,由于「教国」施压,高额的盐税继续折磨着其它两国。「王国」担心盐铁大战再次爆发,为缓解因贸易失衡而导致的三国之间的紧张局势,决定提议三国共同开采位于「王国」的新铁矿山,一切也因此而展开

男主瑟雷诺亚是「王国」底下三大诸侯国之首「沃荷德」的王子,为了加深「王国」与「公国」的关系,两国决定进行联姻。男主的未婚妻芙雷德丽卡是继承了「罗洁尔族」血统的「公国」的公主。「罗洁尔族」与「教国」有极深的渊源,当年芙雷德丽卡的母亲作为「罗洁尔族」的领袖发现了盐海,可是「教国」贪婪的教皇率领人马将其据为己有并且大肆屠杀「罗洁尔族」,部分「罗洁尔族」平民逃到了「沃荷德」被瑟雷诺亚的父亲保护了起来,没能逃脱的「罗洁尔族」世世代代被「教国」奴役,作为开采盐海的劳力。「教国」对「罗洁尔族」以及本国民众进行洗脑,声称盐海是盐之女神给予信徒最宝贵的礼物,任何背叛盐之女神的判教者都将受到严厉的惩罚

在开采铁矿山的过程中,「公国」发现矿山深处蕴含有大量的岩盐,这一发现不仅会推翻「教国」长久以来对于盐的垄断,更会颠覆女神教的统治、解放「德大教国」民众的思想,进一步来说,这一发现会颠覆诺泽利亚大陆现有的格局。知道了铁矿山内秘密的「公国」率军突袭「王国」,由于事发突然,各国来不及反应,很快「公国」便占领了「王国」。「王国」的国王以及大王子全都被杀,二王子罗兰逃到「沃荷德」,三王女被「公国」作为操纵「王国」的傀儡登上了王位

罗兰王子与瑟雷诺亚等人商讨如何夺回「王国」,他们想到联合「教国」一起对抗「公国」,「教国」实际上并没有拒绝的理由,因为如果放任「公国」继续扩张,战火迟早会烧到「教国」。经历了一系列残酷的战争之后,「沃荷德」联合「教国」击退了「公国」,罗兰王子登上了「王国」的王位,开始进行战后重建工作。但是「教国」的协助不是免费的,他们要求瑟雷诺亚交出其领地内的「罗洁尔族」余党。在见识了「教国」内「罗洁尔族」群众遭受的非人待遇后,瑟雷诺亚坚定的拒绝了其要求。「教国」得到回复后非常愤怒,决定进攻「沃荷德」。由于「王国」刚被收复,实在没有能力抵抗「教国」的进攻,就在千钧一发之际,瑟雷诺亚发现了岩盐,也了解了盐之女神不过是蒙骗「教国」民众的手段。瑟雷诺亚以此为要挟,如果「教国」不撤军,他将戳穿「教国」的骗局。最终「教国」选择了撤军,最后的抉择也就此展开

罗兰王子为首的和平派认为应该将岩盐交给「教国」,只要能避免战争,百姓过上和平的日子就算失去王位也在所不惜;以芙雷德丽卡为首的理想派认为应该趁着「教国」与「公国」交战期间,救出被奴役在「教国」里的「罗洁尔族」,大家一起去寻找芙雷德丽卡母亲提到的「罗洁尔族」故乡——「大海」,那里有着取之不尽用之不竭的盐,从此远离诺泽利亚大陆的纷争;剩余的斗争派认为应该联合「公国」,利用他们的技术,进攻「教国」,打破他们长久以来对盐的垄断,只要打败「教国」,解救「罗洁尔族」也不在话下

事实上并没有完全正确或者完全错误的道路。虽然「教国」利用盐之女神的说法洗脑民众,但是由于他们掌握着盐的开采,因此国家富强,人民平等幸福(除了「罗洁尔族」)。罗兰王子的想法是非常伟大的,为了大陆上全体百姓的利益,他能放弃自己的权贵;芙雷德丽卡的想法实际上有着极大的风险,如果传说中的「大海」不存在,他们将会无路可退,最终走向灭亡;斗争派的想法看似是最优解,只要打败「教国」,盐与「罗洁尔族」都将获得自由,但战争是残酷的,这个过程中不可避免的会造成更大的经济损失、人员伤亡

作为游戏最后抛给玩家的一个选择题,我确实沉思了良久,除了和平派的道路我坚决不考虑以外,我一直在理想派和斗争派左右摇摆不定。最终我选择了理想派的道路,原因很简单,无论是游戏还是现实世界,我尊重每个人的信仰以及意识形态,但我厌恶统治阶级将其作为洗脑的工具,所以我决定拯救「罗洁尔族」,告诉他们盐之女神的一切都是假的,大家应该团结起来反抗。实际上斗争派也能达到这样的效果,但是从游戏开始到最后我经历了太多场战斗,见识到为了胜利可以将平民的房子焚烧以挫敌的手段;见识到在「公国」统治下的「王国」废除了王族血统制,有能者居之的自由思想;见识到战争下人人自危,明明是统治者的决策,却要百姓承担后果的结局。综合以上考量,为了将伤亡降到最低,我选择了理想派的道路。换个角度来看,如果现实世界发生类似的事情让我选择,我可能会选择斗争派,即便战争是残酷的,但结果某种程度上是可预见的,而理想派的结局是模糊的,如果找不到「大海」,所有人都将没有未来

最后,我想聊聊游玩《三角战略》给我带来的感悟。首先从游戏的第一次矛盾冲突开始,我对于「公国」入侵「王国」是非常惊讶以及愤怒的,但是帮助罗兰王子重新收复「王国」后,我的想法发生了改变,主要是因为收复后国民的态度。在「公国」统治期间,它并没有采取高压政策强迫百姓服从,而是大刀阔斧进行改革。首先是废除「王国」中的王公贵族制度,采取用人不问出身的策略,只要有能力,人人都有机会升官发财。而当重新收复「王国」后,血统王族制度重新恢复,百姓因此并不买账,甚至从交流过程中我能看出百姓有些怀念「公国」统治的时期。基辛格说:"权力是最好的春药",我看自由也不遑多让,一旦呼吸过自由的气息,就再也回不去了。或许这也是罗兰王子最终选择和平派的原因之一,他也意识到大势已去,再想笼络人心也难了。通关游戏后的我回过头再来评价「公国」入侵「王国」这件事,似乎很难给出一个对错的界定,甚至我偶尔会想,难道就一定要收复「王国」吗?

其次是关于「教国」的思考,实际上我个人觉得是关于意识形态的思考。"意识形态"这个词最早可以追溯到18世纪,法国学者特拉西认为意识形态是专门研究人的观念的学科;马克思认为意识形态是一种虚假意识,是一个谎言系统,是统治阶级欺骗被统治阶级的一种方式。西方马克思主义学者阿尔都塞1970年在书籍《意识形态与意识形态国家机器》中提到两个概念:国家机器与意识形态国家机器。其中国家机器包括军队、监狱、法庭等,它发挥作用主要是依靠暴力,因此如果只依靠国家机器维持统治是很脆弱的,所以还需要依靠意识形态国家机器。意识形态国家机器包括宗教、教育、家庭、工会、传媒、文化、体育......,以宗教为例,宗教为了渗透自己的意识形态往往会通过一个很重要的方式——仪式。《三角战略》中的盐之女神教规定每到特定的时间,所有人都要停下手中的活,面向盐之女神像进行祈祷,这就是一种仪式,通过仪式可以建构仪式感,有了仪式感就会让人产生信仰。阿尔都塞有一句话非常经典:"不是你相信上帝所以跪下,而是你跪下以后就相信上帝了"。世界上没有人没有意识形态,人一旦产生某种观念,他就必然处于一种意识形态中。关于我对意识形态的看法,前面我已经提到了,因此这里便不再赘述

最后我认为,SQUARE ENIX想要通过《三角战略》这款游戏告诉我们:"每个人所做的选择没有对错之分,有的只是立场"

☑️ ☆

致谢

“终于要毕业了”,我常常会这样想。伴随着对未来的一丝期待和恐惧,我想对自己的研究生生涯,甚至是学生生涯做一个不算正式的告别。

“研究生只有刚考上和毕业时才是快乐的”。诚然,考上研究生的那一刻,我确实感到了无限的喜悦,当下有多少考生为了薄薄一张入学通知书正在奋笔疾书,可是每年成功上岸的却又寥寥无几,与他们相比,我是幸运的。而此刻即将毕业的我,同样也因为两张薄薄的证书正在努力奋斗。扪心自问,回首这三年研究生生涯,快乐的瞬间其实并不少:每个月助学金到账的时候、每学期导师发科研津贴的时候、论文被期刊接收的时候、拿到奖学金的时候......如此看来,三年的时光似乎并没有让我摆脱低级趣味,我仍然是一个功利、庸俗的普通人,可是做这样一个普通人又有什么不好呢?从始至终都是如此,我们登上并非我们所选择的舞台,演出并非我们所选择的剧本。悲剧的是:剧本是好剧本,而我不一定是位好演员。

“关键是要问题驱动”,这是我的导师---教授常挂在嘴边的一句话。或许在研究生期间我读的论文没有其他人多、发表论文没有其他人多、交的女朋友也没有其他人多,但是导师对我的指导却不比其他人少。在老师的支持下我才有科研经费进行研究、在老师的帮助下我才能完成论文撰写以及修改。可实际上,老师对我最大的帮助是传授于我“问题驱动”的思想,这个思想会在以后很长一段时间的工作和生活中影响我。我很庆幸自己选择了---老师作为导师,这是我读研期间做的最正确的事。

感谢计算机科学这个专业,它让我多了一种观察事物的角度;感谢《斗破苍穹》有声小说,它陪我熬过了无数个难眠的夜晚,帮我建立了为数不多的自信;感谢任天堂、Square Enix等游戏公司,它们让我的意识超越了时间、地点和金钱的限制,带我领略了一个个精彩、紧张而又深邃的冒险故事。最重要的是感谢我自己,感谢自己有着破釜沉舟,坚韧不拔的品性、感谢自己在许多人生交叉路口做出了正确的选择、感谢自己所经历的一切,正是这一切构成了独一无二的我。

这篇致谢很轻,它仅仅是我毕业论文的一角,甚至打印出来也不过薄薄一张纸。可是这篇致谢又很重,它承载着我三年的总结和感悟,需要很多人的帮助才能撑起这篇文章。“长风破浪会有时,直挂云帆济沧海”,感谢各位同学、老师、家人以及朋友。

☑️ ☆

《满江红》的平庸之恶

事先声明,本文不涉及剧透

大年初五,我抱着批判的眼光观看了《满江红》,这也是我今年看的第一部电影。有的同学可能好奇为什么我没有选择《流浪地球2》,原因很简单,因为我没有看过《流浪地球1》,不清楚他们之间是否有剧情的关联,因此我想抽空看完《流浪地球1》之后再看《流浪地球2》。为何是“批判的眼光”,这个不难理解,近些天讨论热度最高的莫过于中国电影,其中的零零种种,似乎也不需要我再赘言

在看《满江红》之前,我根本不知道这部电影讲述的大体背景。说来惭愧,要不是看了电影,我甚至都已忘了这曾是八年级学过的课文。看来导演高估了我的文化水平,作为一个初中毕业十多年的人来说,很难仅凭标题联想到故事背景。不过我猜,和我相似的人亦不在少数。坦白地说,这部电影对我的最大作用是给我上了一堂历史课,以前我只有“秦桧”、“岳飞”这些模糊的概念,看完电影我方才知道,原来他们是同一朝代的人,而“精忠报国”中的“国”指的便是宋

电影剧情大概讲述的是宋朝宰相秦桧与金私通的信件偶然丢失,秦桧命人寻找所发生的一系列反转再反转的故事。单论剧情,如果10分满分,我会打7~7.5分。原因有很多,首先剧情可以分成两个阶段,第一阶段是找信,这部分由于带着悬疑内容一直吊着观众胃口,所以观感倒还不错。第二阶段是信找到以后,众人的处理方式及其结果。不同于第一阶段,第二阶段时各角色的目的悉数展现,因此此时观众更像是上帝视角看着每个人的命运走向。仅将两阶段的故事讲好,我觉得就可以打6分,至于多出来的分,我要给到反转部分。不过成也反转,败也反转,这也是为什么我不给8分甚至更高的原因。首先第一个反转为我们点破了关键人物的身份,给我一种“凶手原来是他”的震撼。但是,这个反转给的太早了,电影接下来大半的时间我都是在一种”已知凶手是谁,看看他还能翻出什么浪花“的感觉中度过的,这种感觉说实在少了些许趣味,但好在接下来剧情的一系列反转尚能为观众填补一些乐趣。第二个扣分点是电影临近结尾时的反转,也许是大部分电影都要表达”邪不压正“的主题,所以我实际上很早就猜到了最后的结局,因此在我看来构不成反转,倒是让我有些审美疲劳

接着是演技,或者说演员&演技,这也是网上争议颇大的部分。在我看来,这部电影中有两个人格格不入,第一是沈腾,第二是易烊千玺

先说沈腾的部分,这部电影中大部分喜剧情节都源于沈腾,而喜剧的内容需要表演和台词共同传达。沈腾的表演给我一种舞台剧或是小品的感觉,这是他最擅长的部分,或者说是他的舒适区,但是放在这样一部气氛有些紧张甚至肃杀的电影中似乎不太合适,上一个给我这种感觉的演员是陈赫。沈腾的台词相比演技就更让我别扭了,电影的背景设置在宋朝,按理来说演员台词应尽量避免太过于白话,不是说不能用白话,而是应该少用。与之相对的是张译饰演的角色,张译的台词介于文邹邹和白话之间,这才是我认为古装电影应有的台词水平

如果说《满江红》惹人争议的部分是演员,那么演员中最惹人争议的便是易烊千玺。很难找到一个词描述易烊千玺的演技,如果他的演技从头烂到尾,我可以直接说烂。正因为他的演技并不是从头到尾一无是处,也有高光的部分,所以很难形容。但是,再如何高光,在张译、雷佳音等一众老戏骨面前也显得平庸了许多。我首先要吐槽的便是其形体,易烊千玺饰演的是军队统领,按理说一军之将其身形即便不说高大,但至少应该站如松、行如风。可他却正好相反,永远驮着背,脖子也有些前倾,这种形象很难让观众相信他能统领军队。并且他的形象,从发型到面容再到着装似乎与“日本大佐”有些异曲同工之处,实在容易让人出戏

最后是关于服化道的问题,注意,场景布置也属于服化道的部分。《满江红》的场景非常朴素,经常是一群人在一个院落中商谈,亦或是在石巷中行走,室内场景不多,即便有,布置也非常简单。实际上这种场景布置我并不觉得有什么问题,因为《满江红》并不涉及战争等大场面,它本质上和《扬名立万》差不多,讲好故事是首位。真正的问题在于,《满江红》宣传时称电影成本达到了5亿人民币,以我外行人的眼光,怎么也看不出用了5亿。不过,如果把宣发等电影制作以外的工作也算在成本里的话,倒是勉强能理解了

实际上在我看来《满江红》不是一部出彩的电影,也不是一部糟糕透顶的电影,它仅仅是一部平庸的电影。可是平庸的影视作品有很多,甚至在我看来有些捧的比较高的作品其中也不乏平庸者,但似乎也不是每个都像《满江红》这样引来大量的口诛笔伐。为什么《满江红》会从一开始集体意淫式的狂欢,到现在集体癫狂式的谩骂,这个令我很感兴趣。究其原因有很多,抛开最近“幽灵场”、“偷票房”、“买票房”等指责不谈,我不是电影从业人员,对这方面着实不了解。实际上我看这部电影是冲着张艺谋的名头去的,就好像姜文导演了一部电影我也必看一样。但最终《满江红》带给我的落差很大,它没有达到我心中的预期,算不得神作,也谈不上糟糕,介于可看可不看之间的一部作品。如果这是一个新人导演的作品,我会觉得还不错。可问题就在于它是一部花费5亿人民币,并且由张艺谋导演的作品,最终呈现的效果着实难以让人买账

☑️ ☆

我想聊聊火焰纹章·Engage糟糕的角色设计

以下内容无剧透,放心阅读

关掉火焰纹章·Engage(以下简称“Engage”)之后,我意识到低幼的人设或许正逐渐变为日系游戏的“政治正确”。注意这里的zzzq打引号。因为我觉得还没到真正zzzq的程度(实际上也并不存在),但似乎真的存在这种趋势。以前看到一部关于讲述“日本动作片”的纪录片,里面提到:‘“日本动作片”的女演员存在年轻化,演技偏幼龄化(故意将自己打扮成小孩子)的情况,日本男性观众的审美似乎正在向着“幼龄化”转变’

image.png

上图是我从Engage中挑出的几个角色。它们有一个共同特点——整体看上去都像是小学生,或者说给人感觉年纪都非常小。我并不否认在Engage中也有看上去年龄偏大的男性/女性角色。但实际上这些“小学生”的占比还是非常大的。纵向对比历代火纹作品中的角色,Engage的角色设计是令我感觉最低幼的

我从不认为小孩子不能拯救世界、不能参与战斗。中二少年救世界一直以来都是JRPG的特点之一。但是,角色行为需要符合逻辑,角色设计也要符合剧情。以dq11为例,主角从出生起就是勇者,这是他的宿命,所以我们会看到一个大概初中生模样的主角肩负起了拯救世界的任务;以火焰纹章·风华雪月为例,三个国家的角色中,年龄看上去是“小学生”的顶多一到两个。Engage同样涉及到国家间的战争,但是各个国家的队伍中,年龄看上去像是小孩子的却有很多,这不禁让我思考,难道这个国家没人可以战斗了吗,需要拉小孩儿当壮丁。我想强调,我并不是讨厌低幼的画风以及人设。比如许多动漫番剧中的“小孩子”形象并不少,我也觉得挺好看的;再比如,虽然我没有玩过原神,但是原神中很多可爱的角色形象倒也挺让人印象深刻。但是,角色设计应该要符合世界观设定,明明是国家间打仗的剧情,可是战场上却有很多“小孩子”,这个我觉得有点难以理解

最后,稍微吐槽一下Engage的主角设计。首先这作的角色设计师是MikaPikaZo,我对这位画师并不了解,不过Engage的主角设计确实令人印象深刻,交叉的流海、红蓝的配色、与发色颜色相反的眼睛颜色。我第一眼看到主角有一种“眼前一黑”的感觉,因为实在是有些丑。不过所谓“萝卜青菜各有所爱”,我相信有人喜欢,也有人不喜欢,每个人的审美不一样,这很正常。实际上这种杀马特的发型设计广泛存在于JRPG中,作为一名JRPG的爱好者(我是FF的铁粉),倒也见怪不怪

综上所述,仅从角色设计的角度而言,相较上一作风花雪月似乎有些退步。不过,锅也不能全部甩给角色设计师,说白了MikaPikaZo只是乙方,真正拍板决定到底要不要用该立绘的是甲方,所以IS社也有责任

☑️ ☆

我的秋招经历

首先介绍一下我的背景,我本科就读于一所双非软件工程专业,后考研到了末流211的计算机科学与技术专业

准备阶段

我的秋招大概是从8月底开始的,具体应该是英语六级出分的那天,当我得知自己的六级过了以后便从淘宝下单了三本书。从8月底便开始了无止尽的刷题。刷题的内容主要是行测,行测全称为行政职业能力测试,是几乎所有国企和公务员考试都会考的内容。行测里分很多内容,例如小学数学题、小学语文题、资料分析、常识题等等。由于行测的题量比较多,计算量相对也比较大,为了考一个好成绩,必须要刷题练习

除了上图的三本书以外,我还在网上做了不少题,这里安利一个比较好的刷题网站——华图题库。这并不是给华图打广告(麻烦华图给我点广告费),我觉得华图的这个网站做的确实不错,题目全都按照类别归类好了,需要补强什么知识点可以专门进行针对性的训练,而且做题的时候还有自带的计时功能,每次做完之后可以看看自己的做题速度有没有变快

我不喜欢用手机刷题,其中一个原因是字体太小,对于我这种"精神老年人"很不友好,而且对很多人来说,手机刷题可以充分利用碎片化时间,这对我来说也没什么意义,因为我基本上每天都有大块儿时间,不存在碎片时间。具体刷题数量可以参考上面的图,数量关系部分我就做了有至少613题。我是按照各个专题进行刷题的,并且每次做完都会将正确率和时间记录下来,观察自己的变化,看看哪里还有薄弱的部分,哪里需要进行加强

刷题确实很辛苦,下面是我打草稿用掉的A4纸

有时候会忘掉一些知识点,因此我也画了不少思维导图方便复习

为了应付一些私企的考试,我也有刷算法题。相较于行测来说,算法对我来说是相对简单的,因为我本科就有参加算法竞赛的经历,所以对于一些algorithm不需要专门再去学,只要做题就行了。不过我也并没有去Leetcode刷题,因为我个人觉得私企笔试的时候是给定时间限制的,并且别人不会告诉你这个题考的是什么算法。而刷题首先你知道他考的是什么算法,并且没有时间限制,所以这对于上机笔试并没有太大帮助,因此我只参加算法比赛来锻炼自己。算法比赛非常类似于私企上机的过程,都是在规定时间内给你几道题让你解决,并且不会告诉你这些题考的算法是什么,需要自己阅读以后思考,然后编程解决。这里列几个我参加过的算法竞赛网站:

首先是Leetcode,它的优点在于有中文,并且题目风格也类似私企笔试题。缺点是一周只有两次比赛,并且其中一次的时间还是晚上非常晚的时候,因此对于我来说相当于一周只有一次,次数太少

其次是牛客网,它的缺点是比赛题目都是由acm选手出的,因此质量参差不齐,并且题目描述也不是很规范,和私企笔试题的风格也不太像

codeforces是我以前本科经常参加竞赛的网站,但是比赛时间也比较阴间,大概都是晚上11点开始,不适合现在的我

atcoder是日本的算法竞赛网站,所以比赛时间对于中国人来说比较友好,大概是晚上7、8点左右开始


笔试&面试

从9月初到12月我投了非常多的公司,有小厂,有大厂,有国企。这里说几个我印象特别深的企业

亿纬动力:笔试是以手机问卷的形式给出的,考的是行测的内容,大概不到40题。考完之后大概过了1个星期左右面试,分两面,一面大概简单问问是哪里人,问了一个和同事起冲突怎么办的问题。二面算是半技术面,因为你说他问了技术也算问了,说没问也算是没问,问的问题是当时比较火的"羊了个羊"游戏,如果你要写程序自动玩这个游戏,应该怎么办?我理解的是要设计一个比较好的算法去分析当前局面,因为羊了个羊第二关四周有一些堆叠起来的卡片,如果让我设计程序,我应该会采用类似贪心算法的方法,优先消掉四周的卡片,多暴露出更多的卡片,暴露的信息越多,可选择的余地也越多。最终拿到offer,具体数字就不说了,一年大概15w左右,工作地点在荆门,就在我家出门10几公里的地方。不过我毫不犹豫的就拒了,主要是因为我想进国企,国企中我最想去的是中石化

专利局审查中心(湖北):笔试内容有4篇英语长文翻译(英译中)和一篇作文,浏览器考试,双摄像头全程监控。面试内容是提前15分钟让你阅读一份专利文件,之后面试官会考你这个专利的相关内容。可能是面试没发挥好,没拿到offer

三桶油:中石油、中石化、中海油考的都差不多,都是行测+时政+企业文化的内容,但是对于其他企业来说,时政和企业文化的占比会比较高,大概有个30分左右,剩下70分都是行测。中石油我考了72.5分,分两面,一面上来让你阐述一下你报考这个岗位的优势,然后是一段英语听力,让你简单说说这段内容讲述了什么内容,接着是根据你简历上的内容用英语对你提问,我在简历里写了我是一个拥有7000粉丝的b站up主,然后面试官就用英语问我,你平时会上传一些vlog是吗?你有多少粉丝?英语环节结束后,最后是一个开放性问题,你怎么看待"没有规矩不成方圆"和"要创新必须要打破规则"这两句话。还没等来二面通知,我就已经签约别的单位了

中石化是我最想去的单位,也是我最后签约的单位。笔试我考了73.4分,报的岗位是信息工程技术岗,大概有80人进面,招10个人。12月2号面试,12月6号下午接到录用通知,当天我就完成了签约,具体细节就不说了,感兴趣的可以私聊问。实际上我的整个秋招过程所有环节都在为中石化做准备,前期刷题我买的是中石化的书,参加其他企业的笔试也是为了测试自己的做题速度,为中石化笔试做准备,参加其他企业的面试也是为了锻炼自己的脸皮,顺便锻炼自己谈吐,为中石化面试做准备。说说我为什么最想去中石化,勉强来说,我可以算是"油三代",我的奶奶以前是石化的员工,我叔叔(我爸的亲弟弟)和姑姑(我爸的亲妹妹)也都是中石化的员工,我住的小区叫石化小区,我上的小学、初中、高中全部都带有"石化"字样。以前上学的时候,吃早餐可以看到穿着石化工服的员工,中午放学可以看到石化的班车......毫不夸张地说,"石化"这两个字肯定刻在我灵魂的什么地方了。所以当我在考虑找工作的时候,我毫不犹豫的就决定一定要进中石化,中石油都不行,必须是中石化。最后也算是如愿以偿

☑️ ☆

初中同学聚会有感

10月3日这天,荆门温度最高有38度,过了3号气温将会急转直下,例如我写这篇文章的时候已经在家穿了四天的毛衣了。本着明知不可为而为之的精神,我和几个初中同学相约在3号最热的这天举行同学聚会


我们上初中周末经常约着一块儿网吧通宵,所以群名叫“通宵专业户”

这次是我们第二次同学聚会,第一次是2019年2月,大家在饭桌上约定以后每年都聚一次,没想到第二次聚会一晃就过了三年,中间因为疫情或是其它原因没能聚成。第一次聚会有8个人,那时候大家都还没有大学毕业,第二次聚会只有5个人,却只剩我还在读书。第一次同学聚会的时候我们在饭桌上滔滔不绝地聊着以前的事儿,就好像重新上了一遍初中,讨论我们8个人谁被班主任揍的最多(首先排除我),谁抄作业被逮到的最多(首先排除我),谁和哪个女生是冤家......

在参加这次聚会前我预想了很多,例如大家的样貌变化、身份变化、第一句话该说什么,甚至为了饭后的网吧开黑环节,我提前好几天训练了一下自己的英雄联盟(以下简称LOL)水平


夸下海口,表示我要carry他们

见了面以后我才发现大家和三年前比其实没有什么太大的变化。我们都很好奇对方的近况,于是在饭桌上轮流进行“拷打”,问问最近过的怎么样,在做什么,有没有女朋友之类的


胖子

首先是胖子,我对他算是最了解的,今年7月我去襄阳找胖子玩,当时他正一边上班一边考研。这次见到他,他说不考研了,问他为什么,他说因为今年研究生缩招,不好考了。我没继续说什么,或者说我早有预感,以我对胖子的了解,他不是一个做事坚持的人,在学校有老师管着的时候如此,更别说没有老师监督的时候了。关于更多胖子的故事,可以看我之前写的文章我与胖子的二三事&暑假杂记-1


梁总

然后是梁总,群里昵称叫“瓜瓜乐”的就是他,群名也是他起的。以前他是我们几个中打LOL最好的,好到上大学的时候可以靠接单代练养活自己。还记得初中我和梁总的一件趣事,晚上我在他家楼下等他去网吧,他从上面丢下来一个纸团,上面写着:“等会,我爷爷睡着了我再出来”。梁总在现在安徽某公司上班,他们公司有入党的机会,最近刚成为预备党员,也算从良了吧


虎哥

虎哥是我们这些人中最腼腆的,平时话也少。别看他戴个眼镜斯斯文文的,初中班上男生跟他比扳手腕没几个能超过4秒,平时也没见他健身,我们总说他名字里带个“虎”,所以天生神力。初中的时候有个学姐,个子高高的,人也很漂亮,天天下课就来我们班后门口找虎哥,给虎哥送各种礼物,但是虎哥对人家没任何好感,礼物也从不收,后来这事儿被我们班主任知道了,找那个女生谈话,此后她就再没来过了。虎哥目前在荆门某4s店当销售,我们这伙儿人两个有车,其中一个就是虎哥,另一个是胖子


邱总

邱总最初和胖子在一个高中,后来学艺术所以转学了,最后以艺术生的身份和我考上了同一所大学,大一的时候我们还约在学校附近的网吧通宵过一次,后来觉得通宵身体有点顶不住就再没去过了。关于邱总的工作,这里不方便说,便略过了

在聊天的过程中,我问了一句:“谁现在有女朋友?”,大家相视一笑,没人开口。可能因为谈到了女性,话题被转向了我们初中的那些女同学上。首先想起的是我们初中三年的班长,她是我们所有人心中的女神,用“出淤泥而不染,濯清莲而不妖”来形容似乎有过之而无不及,最后一次关于班长的消息源自她的QQ空间,大致内容是她直博首都医科大学了。不论好坏,极端往往更容易被人记住,班长如此,我们班上另一位女生亦是如此。我们班主任几乎不对女生动手,除了这位女生,她因为收低年级学生保护费这件事被我们班主任扇了几巴掌,另外还有一些违法的事儿,就不在这儿细说了。后来我们又谈及了很多女生的名字,但是大家很久都没有联系,也不知道她们最近在做什么就略过了。邱总最后开始揭我老底儿,提到了我们班的一个转校生,迫于他们的拷打,我只好和盘托出。这个女生姓刘,她的名字起的很不错,有“瑞雪兆丰年之意”。大概是初二上学期的时候她从别的学校转来我们班。有一次无意间我在老师办公室看到了各个同学的出生年月日,清一色1998中的一个1996格外显眼,望向姓名俨然便是她。某个星期六我坐公交回家,公交停在某一站的时候我看到了站台边的她,现在很难回想我当时的感觉,或许和《赛博朋克 边缘行者》中大卫第一次见到露西时候的感觉一样。之后在班上我会偷偷注意这个女生,发现她不属于好好学习类型的时候我松了口气,因为这样我每天就可以把作业给她抄了。作业一直抄到了毕业,初三毕业的暑假相当漫长,我也记不清是几月份了,某天她给我发了个消息,说是生病了,希望我能去看她,我问她想吃什么早餐,她说:“肯德基的皮蛋瘦肉粥”。那天我去的很早,不到7点我就进了病房,病房里有两张床,其中一张床上躺着一个女生,另一张床上也躺着一个女生。可能我开门的声音惊动了其中一个女生,她抬起头来看我,我也望向她,确认她不是刘xx后,我径直走向另一个病床。将皮蛋瘦肉粥放在床边的柜子上,瞅了眼她还没醒,于是搬个了个板凳坐在她旁边开始玩手机。由于好奇她得了什么病,我起身走向床尾,拿起病历簿看了看,具体内容我记得不是很清了,只记得四个字——“中期妊娠”。说来惭愧,当时我并不认识“妊娠”两个字,只好利用偏旁部首查了一下百度,我已记不清当初得知其含义时的想法,只记得后来默默坐回到了椅子上,没过多久她醒了,我们随便聊了聊,我没有问,她也没有说。离开医院的时候将近9点半,走之前她让我不要告诉别人,我点了点头

饭后是经典的网吧开黑环节,每次聚会吃完饭去网吧上网已经成了我们的惯例。第一次聚会的时候由于人太多,我们只好分两队进行4v4,这次正好5个人,便干脆一起匹配对战了


战绩

打了两局之后我才发现,原来梁总那句“很久没玩了”不是他在谦虚,看得出来他真的很久没玩了,以前只要他在,我们随便玩都能赢,那天我们被连续暴捶了几局,直到最后才赢了两把

到了下午5点多,我们一块儿结账下机,梁总有点事就先打车走了,剩下我们几个决定走回去。走路回家也算是经典环节了,初中的时候我们通宵完无论多累,出了网吧都会先找个地方吃碗面,吃完之后走回家,没有别的原因,就是想硬撑着表示自己通完宵一点事儿没有,实际上到家之后完全顶不住,倒头就睡了。第一次聚会结束我们也是一块儿走回家的,但那次走回家不是谁为了硬撑,或许是为了珍惜哥儿几个好不容易聚在一块儿的机会,想再多聊聊,至少我是这么想的。这次回家的路上,大家的话并没有我想象的多,甚至很多时候一两分钟没人说话,谈论的话题也从原来的天马行空变成了就业形势、工作情况等。我家住的最近,因此每次都是我最先离开。到了小区门口,我记不清说了几次“拜拜”便与他们分开了

☑️ ☆

研二总结

不知不觉我也要研三了,回顾研究生在读的两年里,对我影响最大的并不是学校内的生活,而是寒暑假的经历

2020年暑假,那时候我还只是一名准研究生,因为很早就进入了老师组里,所以即便还没开学我就开始了学习。因为我觉得需要把自己学到的东西清楚讲出来才算学懂了,所以每次学完什么东西我都会录一个视频上传到b站。从一开始参加组会听不懂师兄师姐在说什么,到后面我可以进行组会分享,那段时间我个人感觉提升非常快,更具体的内容可以看我的2020总结。不过在那篇文章中有件事没有提到,这件事至今都让我非常后悔,那便是我和女朋友分手了。其实早在这之前我们便分手过一次,当时因为我特别喜欢玩galgame,说白了就是有点深陷二次元,再加上我的很多直男操作她有点无法接受,于是便分手了。自那次以后我深深的反思了自己,大概过了3个月我们又和好了,那时候是5月,导师已经开始给我们研0布置学习任务了,那段时间我压力非常大,时间都是以周为单位,因为每周日都要开组会,所以我需要规划每周学什么东西。由于我自己实在无法兼顾学习和恋爱,再加上还有异地这个因素,所以我直接向她提出了分手。不过后来我换了导师,压力也没那么大了,所以我一直在想要是当初没提分手会怎么样呢?虽然我是唯物主义战士,但我偶尔会用宿命论来给自己开脱,例如我会想即便当初没提分手,后面可能也会因为各种各样的原因分手,这就是我和她的宿命,写到这里我突然想起一句歌词:「你我如同交界线,分不开也没有交点」

2021年暑假每一天似乎都非常平淡,每天无非就是早上起床上班,中午回家吃中饭,下午继续上班,晚上下班,周而复始,更具体的内容可以看我的后会有期,江湖再见这篇文章。不过这个暑假也让我意识到了生活似乎就是这样平淡的,所以我渐渐开始变得有些摆烂,一直持续到现在,这个暑假经历对我的影响非常大,以至于到现在我人生的信条就一个字:“混”,在学校里能混就混,毕业了赶紧找个单位混一下,以后每天混日子就行了。我很喜欢玩游戏,我经常幻想自己是游戏中的主角,无论是斩恶龙救公主还是游世界观天下,都是英雄所为,也都比现在的我强多了,说到这儿,我想起罗曼·罗兰在其小说《米开朗琪罗》中的一句话:「世界上只有一种真正的英雄主义,就是认清了生活的真相后还依然热爱它」

2022年暑假,也就是今天写这篇文章的时候我已经到家3天了,这段时间我一直思考着在这个暑假要做些什么,毕竟明年我就毕业了,工作以后就没有暑假这个概念了,运气好还能找到有双休的工作,运气不好就只有单休甚至无休了,换句话说接下来我要打一辈子工,想到这我便觉得高中以及大学生活其实真的不算多辛苦,以前我读高中的时候总是觉得要是能立马工作就好了,这样就能财富自由,想买什么买什么,并且可以养活自己喜欢的女生,现在看来这个想法真是too young, too simple。说到这儿,我确实挺怀念高中那段时光的,倒不是说我想重新回去再过一遍,应该说我怀念的是高中时候的我,未来对于那时候的我来说有无限种可能性,好像以后我想做什么都可以,我想变成什么样的人也都行,现在的我似乎并没有那么多选择,并且我相信随着年龄的增大选择会越来越少

说回到暑假准备做什么,首先我打算出去旅游,城市初步定在南京。人们总说「读万卷书,不如行万里路」,虽然万卷书我没读过,但我也算是写了万行代码,天天面对电脑,感觉人有点麻木,需要感受一下人文气息调节调节(说白了就是想出去玩)。接着我应该好好把房间收拾收拾,说到这儿就不得不提我的一个毛病——仓鼠症。不过我应该算是轻症,还没有病入膏肓。我不是什么东西都收集,我将我收集的东西称为"GOG"——Good Old Goods。我没有特别限定的范围,只要它是老物件,并且很有趣就可以,例如老式打字机、磁带机、键盘、游戏机等等,下面几张图展示了我收集的一些东西


老游戏机

坏的游戏机舍不得丢,装裱起来纪念

收藏的各种中古游戏

老磁带机和各种磁带

老打字机

还有很多很多我懒得一一翻出来,就不拍了。我房间本来就很挤,地上还放满了存放这些东西的箱子,本来就不大的空间更是雪上加霜,所以首先我得好好控制自己的收集欲,其次要想办法处理这些东西

最后是暑假期间我要准备秋招了,我想进的单位今年10月底就要笔试了,只有进了这个单位才能更好的混日子

以上便是我研究生这两年来的总结

☑️ ☆

《十三机兵防卫圈》:献给所有年代少年少女的青春群像剧

从去年《十三机兵防卫圈》(以下简称《十三机兵》)宣布登录Switch以来,这款作品一直是我今年最期待的作品之一,不仅是因为广大玩家的安利,更是因为我对香草社这块金字招牌的信任。我最早接触香草社的作品还是在去年,寒假期间我每天捧着PSV,除了玩《最终幻想10》,剩下的时间都在刷《奥丁领域》,现在说起《奥丁领域》大家可能会觉得它的2D手绘画风非常精美,这一点毋庸置疑,但实际上当时吸引我入坑《奥丁领域》的是其中的养成系统以及打击感。卡普空被誉为动作天尊,它的打击感一直是业界领先的水平,但是在《奥丁领域》这款作品上我体验到了不输卡普空的打击感,简单来说,当玩家攻击到怪物的时候,明显感觉有一种顿挫感,就像是原本60帧的视频突然卡到只有几帧,通过这种方式实现武器砍到身体的反馈。关于《奥丁领域》以后有机会再详细写一篇文章

这里我并不会梳理一遍《十三机兵》的剧情,一则我没有那样的本事,实际上我通关游戏后在b站上找了两位up主的解说才真正看懂了《十三机兵》的剧情。二是因为《十三机兵》的剧情如果按照正常的顺序去理解确实是一个还不错的作品,但达不到神作的高度,因此游戏中设定好的体验剧情的顺序就留给各位还没有玩过的玩家,这里并不涉及剧透,我只谈谈游玩《十三机兵》过程中的感悟


"我还是喜欢你,像风走了八百里,不问归期",当我第一次看到「冬坂五百里」这个角色名字时便想起了这句话。就像许多动漫中常见的女性角色一样,「冬坂五百里」——普通的女高中生,叼着面包上学路上撞上陌生男子一见钟情,露出的底裤都是普通的白色。就是如此普通的她,每天却做着不普通的梦

上面两张图是我从网上找有关「冬坂五百里」在游戏内的截图,说来惭愧,由于游戏内几乎没有一句废话,因此我玩的时候全神贯注看台词,完全忘了截图。不过从上面一张图可以看出《十三机兵》的艺术设计是很强的,强在他的背景是动态的,当巴士驶过,远处高楼的霓虹灯光也会随之浮现。说到这里就不得不夸一下美术,游戏中色彩搭配的很好,而且标志性的地点总是用一种颜色进行烘托,这样会给玩家留下很深的印象。例如,在我脑海中对学校的印象就是每天下午放学的夕阳,因此游戏中校园的颜色大部分都是一种黄昏色;白色给人一种神秘,科技的感觉,因此在某些未来的废墟场景中,墙体以及断壁残垣也都是白色

游戏中共有13位主角,每个角色的个性都非常鲜明,因此这里我也不想过多谈及每个角色的特色(主要是因为懒),探索的乐趣就留给各位还没玩过的玩家吧


接下来我想从整体上聊一聊《十三机兵》。《十三机兵》游戏流程宣传上说是分为崩坏篇、追忆篇和探明篇,但实际上可游玩的部分只有崩坏篇和追忆篇。崩坏篇在我看来更像是类星际争霸的RTS游戏,每场战斗开始前,玩家将从13位主角中选择1-6名角色操控机兵进行战斗。这部分刚开始给我的观感是很好的,有一种买文字AVG游戏白送RTS游戏的感觉,增加了游戏的丰富度,并且崩坏篇中某些人物的对话与追忆篇是有关联的,所以崩坏篇整体给人的感觉并不割裂

随着游戏的进行,追忆篇中某些角色剧情的解锁需要崩坏篇推进到对应的进度,所以后期我渐渐感觉崩坏篇有一点拖游戏节奏,甚至有时候我会想如果没有崩坏篇就好了,我就想赶紧体验游戏剧情(这么说来也只能怪游戏的剧情太吸引人了)

再说追忆篇,所有的故事内容都包含在追忆篇中,玩家将在时间顺序、角色顺序同被打乱的情况下体验剧情,因此游戏一上来并不会保姆式的告诉你这是什么世界观,这里发生了什么,一切都需要玩家一点一点推进剧情去理解。这种写作手法让我想到了作家海明威。海明威自己在《午后之死》中写道:"如果一位散文家对于他想写的东西心里很有数,那么他可能省略他所知道的东西,读者呢,只要作家写得真实,会强烈的感觉到他所省略的地方,好像作者写出来似的。"


关于游戏,最后我想聊的是,其实严格意义上讲我并不是机甲迷,例如各位大佬热衷的高达我一点也不感冒,所以我对于《十三机兵》的剧情并没有大部分人那么热衷。正因如此,我的关注点更多是剥离机甲以及硬核科幻的部分。正如香草社自己所说:"这是一部献给所有年代少年少女的故事"。从游戏中我们可以看到高中生常见的一些活动,男生会聚在一起讨论今天去谁家玩;女生会聚在一起讨论放学后去吃什么,又或者是谈论某位学长的八卦。要问我这部分描写的如何,我的回答是很有日式风格,而且很真实。诚然,几乎所有以高中生为主角的日式动漫、游戏都为我们描绘了非常具有浪漫主义色彩的青春,但是在我看来都太克制了,高中生是不会因为明天是世界末日因此今天就不表白了的群体,反倒只有像「关之原瑛」这样的成年人,才会在被「冬坂五百里」表白的时候考虑到自己肩负的责任而无法当场做出回复。《十三机兵》中几乎每个人都有感情线,香草社非常好的刻画了不同时代不同性格的人对于爱情的反应。所以话说回来,除去机甲和硬核科幻的部分,在我看来《十三机兵》本质上讲述的是关于青春和爱的故事

❌