分类目录归档:佳佳教程

[WebGL]使用javascript控制模型形变

此博文由一个话题引出,原话题是通过滑条控制页面上显示3D模型的某个部分,于是我就来尝试了一下。

由于Three.js我也已经2年没碰了,而且在项目里只用过一次,所以并不是很清楚它是否能通过本身的功能达到这个效果,甚至一开始我已经在想手搓点坐标来达到目标了。

但手搓点坐标实在太麻烦了一点,我就回到blender想看看通常用于控制形变的形态键是否可以导出来使用,然后发现确实可以,这样就方便了,只要控制形态键的数值就可以对模型的形态进行定量控制,以下是操作过程: 继续阅读[WebGL]使用javascript控制模型形变

自动裁剪nginx log

今天博客莫名其妙开始报数据库连接错误,重启了之后也还是一样,一看mysql日志,看来又是老问题,硬盘空间被占满了。

每次都要等到出问题了再来删日志实在太麻烦,查了一下nginx也没有自带缩减日志的功能,查到有用logrotate来自动分割和压缩日志的,不过我只是想简单地把日志文件缩小,能看到最近的日志就够了,所以还是自己写个脚本。

代码很简单,用tail命令把日志文件的最后20000行裁出来存到新文件,然后用新的日志文件替换旧文件,把这个脚本放到cron的daily目录中每日执行一次即可

cd nginx日志目录
tail -n 20000 -q access.log > access.log.new
mv access.log.new access.log
tail -n 20000 -q error.log > error.log.new
mv error.log.new error.log

这段脚本把access.log和error.log都裁剪了。

要注意的是这种办法虽然简单,但是如果在tail执行的时候nginx又向日志文件写入了新的内容,这部分内容可能会被丢弃,所以只能用于我这种简单场景,对于日志有严格保存需求的场景不能使用该方法,应该用logrotate。

[node.js]在redis上使用数据搜索

reids本身是一个基于键值对数据存储的内存数据库,也就是只能通过数据的key来获取数据项目,那么它自然也就没有任何数据搜索方面的功能,只能依靠一定规则生成的key来获取数据。

虽然它的本体是这样,但redis也提供了几个模块为其添加了一部分搜索功能的支持,并将这些模块整合为了redis-stack,官网介绍:https://redis.io/docs/stack/,我暂时还没测试它是否可以直接替代原本的redis实例,但就命令形式上来看,应该是兼容的。

本文是对于redis-stack官网上提供的node.js示例记录的笔记。

安装

redis-stack的安装我就不介绍了,直接从官网下载就好,或者使用docker之类的,本文只记录如何使用。

要在node.js中使用redis-stack的相关特性,我们需要redis-om模块,使用npm i redis-om安装进需要它的项目,关于该模块更详细的API介绍可以去其npm包页面上或者github仓库查看:https://github.com/redis/redis-om-node,不过要注意的是官方的示例中有些地方是错的,我会在下面对应的部分说明。 继续阅读[node.js]在redis上使用数据搜索

小米Mix2s修复距离传感器失灵

我的Mix2s不知道从什么时候开始出现了打电话时屏幕不灭,或者灭掉了之后又没法亮屏的问题,甚至还有打电话时有一定概率对方会完全听不见自己声音的情况,

原本我一直以为是刷的LineageOS和这硬件不太兼容,于是想着可能某次更新之后就解决了。

但我最近升了一个大版本之后发现这个问题依然存在,于是我网上查了几天,发现很多人都有这样的情况,而且和系统无关,全都有这种现象。

再仔细一查,发现似乎是因为距离传感器在长时间使用过程中被细小灰尘堵住了,导致它的超声波距离传感器灵敏度变差。

Mix2s的超声波距离传感器位于听筒两边,是从听筒的孔两边延伸出去的两条非常细的缝,长度大约各1厘米,用眼睛不太容易看出来,需要灯光位于一个特殊角度时你才可以发现听筒两边有一部分的缝比旁边要大一点点(如下图),用美工刀片是可以卡进去一点的。

修复方案那就是先用美工刀插进超声波缝,然后把里面固化的灰尘划出来,注意小心点别把听筒捅坏了,能划的灰都弄出来之后用能插得进缝的软毛刷狂捅一顿,再左右刷刷,尽量把能看到的灰都刷掉。

这样处理完之后距离传感器就可以恢复正常的感应距离了,也不那么容易出现卡在一个状态不变化的情况(但由于设计缺陷,某些情况下还是会有距离状态不变的问题,这个无法修复)

[MySQL]在普通字符串字段中存放json数组并索引

之前有一篇文章写的是在mysql中使用json字段时为其中的数组创建索引,它有个问题就是当该字段本身存放的就是一个数组时(不放在对象下的属性中),这样创建的索引不生效,原因不明。因此要使索引生效需要把数组放在对象下的一个属性里。

现在我发现,如果想要在mysql中存放一个可以索引的json数组,其实根本不需要使用json字段,即使是普通的字符串字段存放的json数组也可以用同样的方法进行索引。

比如现在有一个字段tags,类型为mediumtext,在其中一行存放了以下字符串:

[1,2,3,4,5,6,7,8,9,10]

然后将其解析为json来创建多值索引:

ALTER TABLE 表 ADD INDEX tag_idx((cast(JSON_EXTRACT(tags, '$') as unsigned array)))

接着在查询数据时也把该字段解析为json进行使用:

SELECT *
FROM 表
WHERE JSON_OVERLAPS('[1,2]',JSON_EXTRACT(tags, '$'))

在这样的查询中,mysql就会使用到这个json数组的索引,因此如果一个数据仅仅是为了作为数组使用的话就没必要套个对象放进json字段了,使用普通字符串字段即可。

[MySQL]member of 不走索引

刚刚发现程序里有一个语句,是一个unique主键 member of(返回json数组的子查询),但它就是不走主键索引,接着我把子查询换成了一个手写的json串,像这样

SELECT
    tag_id
FROM
    tags FORCE INDEX ( tag_id_unique ) 
WHERE
    tag_id member of (JSON_EXTRACT( '[1,2,3]', '$' ))

发现即使是指定了索引也还是不走索引,可能member of就是这样的机制? 目前原因还不清楚,于是我先用了另一个办法。

继续阅读[MySQL]member of 不走索引

[javascript]字符串映射到固定颜色

碰到一个需要给图表上数据打颜色的场景,我希望对于同一个名字的数据每次出来的颜色都是一样的,于是想了半分钟,搞出了这么个方案

function strToRGB(name){
	let sum=0;
	for(let s of name)sum+=s.codePointAt(0);
	return [sum%128,sum%126,sum%124];
}

原理是把每一个字符的unicode值累加起来,然后对这个和分别取3个余数。

除数选1到256都可以,选多少取决于希望结果出现在哪个范围,我这里为了让结果颜色偏暗,所以选了128左右的除数。

Windows半夜自动开机

首先容我说一句,搞出自动唤醒电脑更新系统这个策略的人是烧饼,搞出更新后无视用户任务自动重启电脑的人也是烧饼,说不定还是同一个人。

从Win10开始就有不少人遇到了这个问题,最后发现是系统更新半夜唤醒了电脑,关闭方法是在“任务计划程序”里找到”\Microsoft\Windows\UpdateOrchestrator\Schedule Wake To Work”这一项,把它禁用,如果提示权限不够无法操作,可以搜索一下如何禁用这个任务计划。

这篇文章我要说的是另一个问题,自从升级到Win11之后,之前在10里面已经改过的设置又被改回来了,又开始每天晚上自动开机跑更新,而且即使再改,它依然会被恢复到默认状态,晚上还是会自动开机,真实烧饼行为。于是只能换个办法来解决这个问题,我找到的一个办法是,既然任务计划唤醒电脑靠的是唤醒定时器,那么只要把唤醒定时器整个禁用掉应该就好了。

关闭方法是在当前的电源计划设置里找到“睡眠”→”允许使用唤醒定时器“,把启用改成禁用即可。现在几个晚上下来都没有再出现自动启动的情况了。

继续阅读Windows半夜自动开机

[ffmpeg]转码后音画不同步

音画不同步多半是在vfr(可变帧率)和cfr(固定帧率)之间转换的时候视频帧时间戳没有更新导致的,不知道为啥ffmpeg会默认以这种一定会导致错误的方式工作,但我们手动加入参数后就可以修正这个问题。

如果是一个vfr视频,ffmpeg默认会转换成cfr,如果不希望它转换的话,则在前置参数的位置加一个-vsync passthrough ,视频帧率模式就不会被转换了,这样只要原视频音画是同步的,那转出来音画肯定也是同步的,因为时间戳完全没有变。

[MySQL]This function has none of DETERMINISTIC, NO SQL, or READS SQL DATA in its declaration and binary logging is enabled

MySQL中创建函数的时候如果出现了这个错误,表示创建语句中缺少错误中所示的3个函数行为声明,只要根据需求加在Begin前面就可以了。

如果你不确定,那就需要加DETERMINISTIC ,如果这个函数不会去操作数据库就写NO SQL (不是完全不能有SQL语句),如果需要读取数据就加READS SQL DATA 。

比如

CREATE DEFINER={{EJS12}}@{{EJS13}} FUNCTION {{EJS14}}() RETURNS int
    NO SQL
BEGIN
	SELECT 1+1 into @r;
	return @r;
END

[Node.js]解决‘gbk’ codec can’t decode byte 0x80 in position

每次换一个环境执行npm i都会碰到这样的问题,记录一下解决方法,

方法1:手动去报错的文件里指定编码为UTF-8,我自己第一次解决这个问题就是用的这个办法,刚刚想找找看有没有别的解决方法的时候发现别人也有去手动改源码的,放个参考链接

简单地说就是找到报错的那行,给open函数加个encoding='utf-8' 参数就可以解决问题,但这样属于改了人家文件,更新后还是会变回去的,所以现在我不这样做了。

方法2:去控制面板的区域设置里到“管理”标签页下,“更改系统区域设置”,把“Beta版:使用Unicode UTF-8提供全球语言支持(U)”勾上,然后重启一下,python就会默认用utf-8来读文件了。

这个方法会改变整个系统的默认代码页,最主要的影响是会导致使用非Unicode的程序乱码甚至崩溃,还有在gbk设置时以ansi保存的含有中文的bat脚本会乱码。如果影响不大的话倒是可以让系统一直保持在这个区域选项上,影响某些软件的正常使用的话在执行完需要的编译任务后还得改回去。在这种模式下可以使用“locale emulator”这样的软件以Chinese模式启动程序,以解决程序的乱码和崩溃问题。

方法3:我没试过,理论上应该可行,从python本体入手,把它的默认编码设置成utf-8,参考这里的方案2。这个没用

[MYSQL]删除JSON数组中特定数字

这问题折腾了我一下午,首先是mysql中没有现成的方法来寻找数组中数字的位置,然后是谷歌百度bing用中文和英文搜索都没找到可用又不烂的办法,爆栈网有一个高票答案,但是似乎并不对,JSON_SEARCH只能用来搜索字符串在json中的位置,数字不支持,不知道他是怎么得到结果的。

经过我晚上的继续摸索,翻遍了官方所有json相关的文档,终于让我拼出了一个方案,就是用JSON_TABLE 先把数组转成表,然后用where剔除里面不要的数字,再用JSON_ARRAYAGG转回json数组,以下是示例代码

set @j='[1,2,5,8,9]';
select JSON_ARRAYAGG(b) from JSON_TABLE(
@j,
"$[*]"
COLUMNS(
b int PATH "$"
)
) as `破mysql连个数组查找方法都没有`
where b<>5;

这样就可以得到结果[1, 2, 8, 9],5被删掉了。

这个方法虽然并不优雅,但也没办法,谁叫MySQL连在数组里找数字的位置都做不到呢。

继续阅读[MYSQL]删除JSON数组中特定数字

[MySQL]对json字段中的数组创建索引

Mysql中在json字段里存放数组时,如果需要快速查找到包含某个数字或字符串的数组,则需要在这个数组上建立索引,其multi-valued 索引能满足这种需求。

在已有表的情况下,执行以下语句创建一个数字数组索引

ALTER TABLE 表名 ADD INDEX 索引名((CAST(json字段->'$.指向数组的对象名' AS UNSIGNED ARRAY)));

这个语句把json字段中的一个数组以无符号数组读出,并对每个数字进行索引,这样要寻找包含某数字的数组时,将使用索引提速。

接下来使用类似这样的语句查找拥有某个数字的数组所在的条目

SELECT * FROM 表名 where 要找的数字 MEMBER OF(json字段->'$.指向数组的对象名');

或同时查找多个数字
SELECT * FROM 表名 where JSON_CONTAINS(json字段->'$.指向数组的对象名', CAST('[1,2,3,4,5]' AS JSON));

使用了该索引后,作用在相关字段上的JSON_OVERLAPS 函数也会使用索引。

 

要注意的是,如果数组不是像{"group":[2,4]} 这样对象中的数组,而是字段中直接存放了一个数组[2,4] 的话,索引不起作用,原因不详,但使用explain解析语句时候就是全表查询。

参考:https://dev.mysql.com/doc/refman/8.0/en/create-index.html