add: blog content
All checks were successful
Build blog docker image / Build-Blog-Image (push) Successful in 1m36s

This commit is contained in:
2024-07-02 16:59:26 +08:00
parent 938315c966
commit f30d6e10af
113 changed files with 4821 additions and 0 deletions

View File

@@ -0,0 +1,48 @@
---
title: 2021年终总结
date: 2022-01-12 16:27:19
tags:
- 随笔
---
# 2021年终总结
2021年已经过去2022年已经来临。每每一年开始的时候我都会展开一张纸或者新建一个文档思量着又是一年时光也该同诸大杂志一般写几句意味深长的话语怀念过去的时光也祝福未来的自己。可往往脑海中已是三万字的长篇落在笔头却又是一个字都没有了。
如今跨年的时候已经过去朋友圈中已经不见文案的踪影我也该重新提笔细说自己2021年中做过的种种。
<!--more-->
## 高考,落下帷幕
在未来我回想2021时想到的第一个念头必然是“高考”都说高考时人生中最重要的分水岭这次考试不仅把我送进了911大学——北京邮电大学也标志着一个时代的结束。
## MY中学杂记
仍然记得,在高中的最后一个寒假,高考前最后一个比较长的假期,我还是没有能够提前写完作业,把有限的时间投入无限的复习大业中去。仍然是到了假期的最后一天再来补作业。
仍然记得,在高考的理综结束之后,我差点跪在铭志楼的楼梯上。
仍然记得,在那天的中午,我们几乎没有吃饭,寝室里出人意料的安静。
仍然记得,在最后的宴会上,我们共同举杯,祝福我们的未来。
## 暑假,说好的狂欢?
在前12年的学生生涯中我们都在期待着这一次的暑假以为在这个没有作业的假期里我们就可以充分的享受人间的美好。可是当时我们不知道这人间的烦恼可不止作业这一种无论是突如其来的疫情导致开学延期还是等待录取时的不安。
虽说在暑假时,拥有了自己的笔记本电脑,可是在高中三年屯下的游戏还是没有玩几个,看来我也是“喜加一”的受害者。虽然在高考后入坑了原神,但是假期间我并没有太过投入的玩。
暑假下定决心要好好的学一学可是看着我gitee上暑假期间那稀疏的提交我就知道我又摸了一个暑假的鱼。
![gitee贡献](./2021-final/1.png)
即使我想写的很多项目都没有被扎实的推进下来但是学习的一些的C语言还是让我受益匪浅。
现在看来,这个假期真是,**学也没有学好,耍也没有耍好**的典型。
## BUPT——新的开始
尽管有着烦人的疫情我们还是在2021年9月8日顺利走进了北邮的校园。
~~虽然校园很小,但是~~校园第一眼给人的印象还是蛮大的。走在贯穿东西的主干道上,我们逐渐地熟悉校园中的建筑物。
在刚开学的时候北邮放假永不调休的制度着实让我们大吃一惊毕竟连着中秋加国庆加周末几乎放掉了半个月这难道是一般人能承受的吗更不要说我们这群刚刚放了三个月的暑假已经不知道学习是什么东西的freshman了。
刚刚享受玩国庆假期的我们,就又被疫情坑了一把,半个学期就这样被我们混了过去,除了把半个寝室都带进了原神的坑里,其他的我啥也没干。
紧接着就是噩梦一样的体测+半期考试+秋之韵三板斧,这难道是一般人能承受的吗?~~反复以表示强调~~
再然后就是期末考试提前,高数与线代的课时数严重不足,其他几科也是组织完期中考试就准备期末考试,总之就是这个学期没有下半期这个说法了。
这个学期就结束了。
**总结:啥也没干**
## 说说技术
在北邮的一个学期虽然学到的的新东西不多但是自己C语言的能力是有了切实的提高。在大学之前也很少接触这种OJ平台的代码训练这个学期也算是涨了见识。
这个学期说好精进一下自己Python相关的技术结果这个学期Python是我写的最少的一门语言。这个学期反而接触了许多新鲜的语言比如JavaC#Javascript等等。自己也租用了阿里云的云服务器在上面部署了自己的博客和一些小工具。除了语言方面的接触这个学期对于智能硬件的接触也算是比较对针对选修课“基于Arduino的开源手机设计”熟悉了Arduino编程控制相关的知识自己也购买了一套Arduino开发板打算下学期做点有意思的小工作。
在学院的综合影视部干了一年我也算是接触了直播的相关流程对需要的技术栈有了一个初步的了解。还研究过V家编辑器感觉自己没用技能又增加了。
## 总结
2021年就是虽然没有什么大的收获但一些小小的进步总让我们确信未来会更好。

BIN
YaeBlog/source/2021-final/1.png LFS Normal file

Binary file not shown.

View File

@@ -0,0 +1,77 @@
---
title: 2022年终总结
tags:
- 随笔
date: 2022-12-30 14:58:12
---
# 2022年终总结
2022是困难的一年。我们需要为2023年做好准备。
<!--more-->
## 总结
尽管人们在撰写年终总结时习惯于”美化“过去一年的境遇但是2022年的情况让我甚至很难用”砥砺奋进”或者“破浪前行”之类的词来形容。
导致2022年这种情况的原因很复杂国际大气候的惊涛骇浪和国内小气候的暗流涌动、新型冠状病毒疫情的反复延续以及我个人的部分特殊情况都能算在其中。
2022年绝对是见证历史的一年而且是大部分人不想见证的历史。2022年2月俄乌冲突爆发7月前日本首相安倍晋三被刺杀8月佩洛西窜访台湾12月巴尔干半岛剑拔弩张。而新型冠状病毒肺炎的防控遭遇重大挫折我们离回到正常的生活更是遥遥无期。“百年未有之大变局”这个提法在2017年末的时候出现在那个时候可能只有少数人明白啥叫“大变局”如今5年过去了可能大家都明白了什么叫做“大变局”。
> 鉴证不是为了过过嘴瘾,而是为了更好的指导自己的生产生活实际。
### 时长八个月的寒假
2021年末12月新冠Omicron变异株在南非首次被检出随即得到命名。在那个时间点上我还不如现在这般关注新变异株的出现和提交也不会知道这个变异株会直接摧毁我在2022年上半年的生活。2022年1月3日我离开学校回到家中而我下一次回到学校就要到8月27日了。
在这8个月的前半段似乎还一切正常。首先是应付因为冬奥会而改成线上的期末考试说来也是奇妙进入大学已经3个学期了我还没有在线下参加过期末考试。然后就开始宅在家的寒假过完一个平淡的年。随着年味散去就开始期待开学的日期但是等来的却是一次次的推迟通知——吉林疫情上海疫情北京疫情随着疫情在一个个地点爆发我们终于意识到自己大学的第二个学期只能完全在家里度过了。
不过讲道理,在家里学习和在学校里学习的孰优孰劣是一个值得探讨的问题。我个人认为,还是在学校里更加的适合学习。学校可以为你提供生活中所需要的一切——食堂、宿舍和图书馆。还有最为重要的安静氛围。北邮的沙河校区我就非常的喜欢,现代化的校区位于僻静的郊外,简直就是学习的圣地。但是像本部之类的地方还是尽快从地球上消失好一点——全校共用的公共澡堂、永远没有位置的图书馆简直就是上世纪八十年代的大学校园,在这里学习是一种挑战。至于在家里学习,我的评价是吾其还也。
> 关于这八个月我有一个更加详细的总结,我在这里就不赘述了。
### 搬校区&大二
进入8月份国内的疫情终于趋稳开始准备回到阔别已久的校园。
可是关于返校的第一个消息就是我们要从美好的沙河校区搬到傻逼的本部——这不仅仅是一个空间上的移动更是一种时间上的移动——沙河校区兴建与2015年而本部则是上个世纪的遗产。
> 这里插播本部笑话二则。
>
> - 欢迎来到北京邮电大学西土城校区,这里有上世纪八十年代北京最好的大学宿舍。——北京邮电大学招生广告
>
> - 年近耄耋的老校友走进学生二公寓,拉了一下墙上的拉绳开关,灯亮了,老校友激动的感叹到”还和我当年住的时候一模一样“。——校庆日见闻
很高情商的说,在本部生活有一种历史的厚重感。特别是你在教室上课的时候注意到墙上展示五十年前校风光的照片上展示的教学楼和你现在正在待的教学楼一模一样时,特别是你晚上提着桶穿过半个校园去洗澡时,特别是你参观老式办公楼一般的图书馆时。
虽然本部确实挺垃圾的,但是吐槽还是得有个限度。
大二一开始是就是大一学年的综合评价。我对此的评价是希望信息黄埔还是做点信息黄埔该做的的事情吧,不要搞得大家天天骂你信息黄泉,明明可以直接让系统自动生成的东西还需要自己手动填写,简直就是垃圾。
在综合评价完成之后,奖学金的评选和专业分流就是顺理成章的事情了。小小的从学校赚了一笔钱,成功进入了自己心仪的计算机科学与技术专业,从这个方面上来看,本学期还算是顺利。
然后是学生组织。执行自己在上半年使所指定的规划,从院团委的宣传部门跳槽出来,加入了传说中北邮最神秘的学生组织——北邮人。~~虽然就目前来看,北邮人略显的有点那啥~~。
然后是大创。作为业界知名的PPT大赛而且还能够在综合评价的时候加分这种你好我好大家好的东西自然是应参加尽参加~~我对于自己大一忘记水一次的这种事情表示:当事人很后悔~~。
小小的总结一下2022年可以算得上是一事无成的一年还搞砸了不少的事情。在写代码上进展有限成绩上大幅倒退说好的六级英语和大学物理竞赛都没有参加在年末应对疫情进展的时候更是把“不知所措”这个成语诠释的淋漓尽致。
![](./2022-final/2022-12-30-14-26-19-QQ_Image_1672381538441.jpg)
关于今年的人际交往和社会关系我愿意用QQ2022年年终总结中的一张截屏来总结这张图片透漏出一种无可救药的悲伤。
![](./2022-final/2022-12-30-14-28-12-QQ_Image_1672381543836.jpg)
## 展望
2023年很有可能还是极为困难的一年不过有了2022年的前车之鉴我相信我们可以在2023年取得比较辉煌的成就。
在思想上,我们提高自己认识困难,处理困难的思想和意识。要摒弃被动迎战的“怕事”思维,积极主动地按照形势的变化做准备。
在疫情的防控方面,我们需要尽快的适应新的疫情流行形势下的工作学习和生活,坚持以科学为导向,坚持生活至上的原则,在保证自己的生命安全的前提之下,尽量的维持原有的生活和学习习惯。在被动适应的同时我们还要主动出击,将工作做在前面,提高自己应对这种黑天鹅事件的能力。积极主动的关心新变异株的流行趋势,预计下一次疫情高峰,采取有力措施避免同病毒正面硬刚。提高自己的防护意识和防护水平,尽量避免一切可能的高危暴露。
在个人的学习方面,坚持学习是为了能力而不是为了分数的思想指引。关注个人实际能力和水平的提升,不要将时间浪费在无意义的竞争之上。采取信息化的措施优化自己的时间管理、目标管理,坚持利用信息化的方法管理自己学到的知识,坚持利用信息化的途径进行学习。要更多的对未来进行前瞻性的思考,通过文字的方式记录自己的思考成果,在这里方面要“务虚”而不是“务实”,更多的对前进的方向进行大方向上的把握。
我们相信2023年将是收获的一年。

View File

@@ -0,0 +1,91 @@
---
title: 2022年暑假碎碎念
tags:
- 随笔
typora-root-url: 2022-summer-vacation
date: 2022-08-22 15:39:13
---
# 2022年暑假总结
在8个月的漫长寒假的最后两个月~~也就是俗称的暑假中~~,我都干了些什么?
<!--more-->
### 学习
- 七天速通`C++``Qt`,搞定了上个学期的计算导论大作业,再用七天的时间整理代码和~~瞎编~~撰写文档,希望能得到一个不错的分数,挽救我那岌岌可危的平均分。
- 开始阅读`CSAPP`~~也就是传说中的没人理解计算机系统~~但说实话阅读的进度真的聊胜于无我用了整整一个月才读完第二章做完对应的Lab甚至Lab中的少数题连网上的题解都不咋看得懂开始怀疑自己是不是真的适合学习这个学科。目前希望在假期的最后四天里面能够创造奇迹拆弹成功~~指完成第三章的`Bomb Lab`~~。
> 学习日记:
>
> 7月1日刷B站
>
> 7月2日刷B站
>
> 7月3日刷B站刷到了其他程序员分享自己学习经历的视频深感焦虑决定明天开始好好学习重新做人
>
> 7月4日刷B站
>
> > 此处致敬了胡适之先生的日记,特此说明
- 开始学习伯克利的`cs61b`,虽然在假期的后半段才开始学习。
- 更新了三篇博客。分别记录了我在学习`Qt`中的一点小收获,我在小组合作中的一点思考和我对未来主力语言选择的迷茫。
- 下定决定要参加下一学期的物理竞赛,但是在听了讲座之后直接决定开学再开始学习,~~我知道我在家没法学习,俗称开摆~~
- 又捡起了`Blender`,并在[Github](https://github.com/tanjian1998/bupt_minecraft)上找到了伟大的前辈们在`Minecraft`里复刻的老校区,希望能用`Blender`渲染几张图当作桌面。
![唯一的一张成品](result1.png)
> 在此感谢所有为此付出过汗水的前辈们,让我这个即将搬入老校区的萌新能提前一睹老校区的风采。
### 代码
- 继续完善我的[邮历](https://github.com/jackfiled/post_calendar_android),虽然目前开发由于一些技术之外的原因暂停了。
- 花了半个月的时间学习`Go`的API开发给[通知大全](https://squidward.top/)的后端做了一点[小更改](https://gitee.com/zoctopus/ddlgo-back/pulls/2)
> `Go`设计的挺好的,就是有点差。
- 写了一个从教务系统自动获得课表和生成`ICS`日历文件的[微服务](https://github.com/jackfiled/JWGLService),合并到上面提到的后端中。
- 做了`LeetCode`上的第一题。
### 游戏
- 买了文明六,但是一分钟都没玩
- 每日原神清委托,抽到了宵宫。
- 入坑崩崩崩,但是已经领了两次回归奖励了。终于推到了第十二章。
> 在第九章一睹传说中“最后一课”的风采。
> 也许我可以把我的Steam账号租出去了买了二十几个游戏总游戏时长还不超过200个小时目前一共就`战地五` 和`CS:GO`这两个游戏我玩上了50个小时。
### 番剧
这个假期看完了:
- 路人女主的养成方法
- 徒然喜欢你
- 中二病也要谈恋爱
- 女武神的餐桌
> 邪王真眼是最强的
现在正在看:
- 终将成为你
> 首先我不是白河豚,其次我不是白河豚,最后我不是白河豚。
### 目前手上还没填上的坑
- 修改我博客的主题。由于现在我用的主题在2017年之后就不在更新bug啥的已经不少了也缺少了一些我想要的功能打算在原本的基础上小修小补。
- 把我的树莓派改造好。在我的期望中这个玩意儿应该是一台全自动的BT做种机寝室里的影音中心再加上我的Arduino单片机应该还可以自动检测寝室的温湿度和控制空调的启动。
- 假期入了[稚晖君](https://space.bilibili.com/20259914)的[Holo Cubic](https://www.bilibili.com/video/BV1VA411p7MD),花了我大几百块钱,但是买回来之后就一直处在吃灰的状态,希望这个学期能有时间来折腾一下这个玩意儿。
### 其他
- 决定退出融媒体中心的综合影视部。
- 和前女友和平分手,希望她能在南京好好的生活。
- 终于参加了一次原魔群线上~~高峰论坛~~面基,见了见久违的高中同学们。

Binary file not shown.

View File

@@ -0,0 +1,52 @@
---
title: 2023年年终总结
tags:
- 随笔
date: 2024-2-29 20:18:19
---
虽然2023年已经过去了两个月但是年终总结还是要发的。
<!--more-->
### 奋进的一年
虽然2022年在混乱中落幕没有为2023年的开幕“奠定一个良好的基础”但在呈上启下之际我们采取果断措施及时适应当前的新形势和新环境成功调整好自己的各种状态。在2023年的工作和学习中取得良好的成绩。
在年初整个人处在消极和悲哀的环境中。从外部大环境上看疫情防控开始转段正常的工作和学习节奏被打乱——或者说整个2022年最缺少的东西就是确定性从个人小环境上看2022年年中同高中的女朋友分手秋季学期存在着离散数学下、数据结构两门我没有学懂的课程学习和生活环境也从条件较好的新校区变成条件较差的本部校区还附带着寝室重新组合等等一系列问题。令人感到遗憾的是面对艰难繁重的工作任务我并没有及时调整好心态反而陷入“面临失败——状态下滑——更加失败”下降螺旋中。上述问题造成最直接的结果就是在大二的上学期取得了大学以来最差的成绩。
2023年就是在这种环境中开始幸而从2023年开始调整自己的状态一是在变化多端的环境中寻找一个长期性的目标紧紧围绕这个目标进行工作给予自己确定性二是主动切断各类社交媒体和零散信息源避免自己接触各种无意义的焦虑和内耗消息三是培养自己阅读的习惯。
从春季学期的成绩来说还是取得了一定的成绩:从需要考试的课程上来看,除了计算机组成原理这门课程的成绩不算理想,计算机网络和形式语言与自动机两门课程还是取得个人较为满意的成绩,而且最重要的是三门课程都还是学的比较透彻。从含有大作业的实践课程上看,数据结构的课程设计让我第一次完整实现了一个前后端分离的应用程序,计算机网络的课程设计锻炼了基于`C`的网络编程,而面向对象的程序设计和形式语言与自动机的实验则在`Java FX``Electron`等其他技术领域进行了探索。而在技术之外,通过多次大作业的合作锻炼了一个合作良好的团队——[post-guard](https://github.com/post-guard)。
相对于寒假,暑假则是一个非常充实的。在暑假开始之初前往南京“处理历史遗留问题”,在回到家之后又找了一个事业单位的信息科见习,在各种意义上提高了自己对于世界的认识。同时通过大创项目进入实验室中学习,开始第一次“体验”科研。
在秋季学期中,面对着操作系统、编译原理、数据原理和算法分析四门重量级的课程和为数不少的选修课,我们延续上学期调整好的状态积极进行面对,取得了良好的成绩。在开学之初参加数学建模比赛获得一个安慰奖,为数学竞赛和物理竞赛贡献了不少的报名费,在这些学科竞赛中虽然没有取得很好的成绩,但是参加这些赛事的经历本身也是一种非常难得的锻炼。
在2024年中我们利用好在2023年奠定的良好基础赓续奋发图强的精神动力更加从容自信地面对前进道路上的各种困难。
### 技术上的进展
虽然2023年是在学习上非常忙的一年但是在技术上还是取得不少的进展。
第一是基本确定了自己的技术路线:以.NET为中心技术在底层开发上练习使用Rust语言在前端界面上练习使用React。如此三个方向的进展基本覆盖了计算机开发技术的所有方面。.NET作为一门较为冷门的面对对象开发语言有着广泛的应用场景在国内尤其是在工控上位机领域应用广泛。Rust作为C++语言的上位替代有着极高的性能和开发难度因此我目前主要作为刷算法题的语言使用。React是目前个人认为最主流的前端开发框架我也很喜欢其函数式的界面设计思想。
第二是将自己的工作环境基本迁移到Linux系统中。Linux作为现代程序运行的主流环境有着很多的好处和坏处好处是对于各种开发工具的兼容性都非常好坏处是图形用户界面是一坨屎。因此我的系列博客“日用Linux挑战”还在火热连载中
第三是我和同学合资购买了一台二手服务器。在这台服务器上我们部署了各种各样的服务和应用,在很大程度上重塑了我的开发工作流乃至于不少生活习惯。鉴于这一点有点离题,我会单开一篇文章进行介绍(开始挖坑)。
展望2024年的技术前进方向我们希望向语言和系统更深的地方进军。深入研究.NET运行时的方方面面兼顾熟悉在.NET生态系统中的各种常用框架技术。尝试推动将Rust语言从算法界面普及到实际应用开发场景中去以嵌入式开发和操作系统开发等为抓手逐渐取代C++语言之前在开发技术工具箱中的地位。对于React在目前所有东西都运行在浏览器上的大环境下完全不懂任何前端显然是不合理的因此合理适度的学习相关知识是必不可少的。
之于Linux我希望继续坚持使用Linux。在日常使用的过程中尝试将上述各种技术同Linux的系统开发和应用开发结合起来为不断完善Linux做出一点贡献。
### 其他有趣的方面
2023年最令我吃惊的事情是我刷B站的时长
![image-20240303165826486](2023-final/image-20240303165826486.png)
容易计算得出我一共看了64天的B站接近六分之一的时间都在看。虽然我确实有着在干活的时候黑听B站和把B站当作音乐播放器的习惯但是这个时间未免有点太长了。下一年一定要在这个方面做出一定的改变将更多的时间放在看书上面去~~虽然写这句话的时候我就在黑听B站~~。
说到看书,在这一年内看来不少的书。在这学期看的最多的还是各种日式轻小说。总体上来说作为一个死宅,我对于各种校园恋爱题材的轻小说还是比较感兴趣的,本年度看完的就有:《我的青春恋爱物语果然有问题》,《路人女主的养成方法》,《继母的拖油瓶是我的前女友》,《关于邻家的天使大人不知不觉把我变成废人这件事》。不过对于各种涉及到世界观的日轻作品我就比较拒绝了,感觉不带脑子看还行,带脑子就有点不行,不过应该还是有不少优秀的作品等待我发现。在中文小说上,这年度应该就看了两本:《北平无战事》和《临高启明》,虽然这两本书在各种意义上差距都有点大。在各种专著上我的兴趣点也不少,比较好看的有《美国反对美国》和《筚路蓝缕 世纪工程决策建设记述》比较枯燥的有《当代中国政府与政治》和《走向自主创新寻求中国力量的源泉》和《新火走向自主创新2》。不过后面两本工业调查报告如果看进去了还是比较上头的那种工业上“冷峻的热血”非常激动人心。
还有不少优秀的电视剧作品。例如《大决战》三部曲和《决战之后》这几部描写解放战争的老电视剧,《三体》这个新锐电视剧虽然在节奏上有点拖沓,但是各种大场面的观感不错和合理的改变还是不错的。

Binary file not shown.

View File

@@ -0,0 +1,116 @@
---
title: 人生代码大作业初体验
tags:
- 随笔
- 感悟
typora-root-url: big-homework
date: 2022-07-27 11:34:49
---
# 代码大作业初体验
在大学也呆了一年了,终于遇上了第一个需要多人合作的写代码项目。从四月底分组完成,任务部署下来到七月初接近尾声,在这两个多月的时间里,也算是经历了不少,学到了不少。
<!--more-->
## 项目背景
项目的主体是一个公交车的自动调度系统。公交车行驶在一个环形的轨道上,站点均匀的分布于其上;系统需要支持在每个站点上创建顺时针上车、逆时针上车和下车三种请求,并调度公交车按照一定的策略前往这些站点处理请求。
> 在一开始我还以为这个策略需要自己优化,通过比较不同组之间调度完成请求需要的时间来决定优劣,想着还有点可怕,后来明确策略的规则是由老师指定。
>
> 不过要是真的按照策略的优化来比较程序之间的优劣,想想还是很有趣的一件事情,不过用在一个计算机专业第一节专业课的大作业上显得就有点那啥了。
项目要求使用C语言实现一个控制台中的核心版再采用 `C/C++`相关的图形化框架实现一个动画版。
整个小组由三个人组成。剩下的两个人有 `Dev C++`的经历对于C语言的语法还算是比较熟悉。
## 项目的管理
### 构建管理工具
在开始一个项目之前,应该先选择一个合适的技术栈。在选择的时候,不能光考虑自己平时的习惯和技术的先进性,还得考虑组内所有人的合作效率,不能让代码就在你一个人的电脑上能跑起来,同时这个技术得是所有人都比较熟悉的,不能说你在那里吭哧吭哧的都把代码写完了,其他人还搁那看文档和教程。
`C`语言项目的管理上,我首先排除了一个文件打天下的“传统”生产模式。这个方案的优点是所有人的十分熟悉,不需要任何额外的技术,也对 `C`语言的IDE没有任何的要求不管你是用初学者的常用的 `Dev C++`还是宇宙第一IDE `Visual Studio`都可以打开这个单独的文件然后编译运行。但是这个方案也就这一个优点了。且不论手工合并很多人撰写代码的复杂繁琐光是一个长达1000行的文件就看得人头疼欲裂了。
其次我排除了 `Visual Studio`虽然VS也算是一个开箱即用的开发平台。第一我自己对 `Visual Studio`不熟悉如果在合作开发中遇到了一些VS的问题我可能也不知道该如何解决。第二我们验收使用的OJ平台采用的是 `GCC`编译器,不同于 `MSVC`编译器,虽然编译器行为不同的情况很少遇见,但为了避免这些一遇到就是纯玄学的问题,我还是采用 `MinGW64 GCC`编译器,这个编译器也算是我常用的编译器。
最后我选择了利用 `cmake`组织项目,`MinGW64 GCC`作为编译器的方案。虽然 `cmake`还是一个比较新的玩意儿,但是只要编译的模板在一开始写好了,就基本上不用再修改了,并不需要所有人都熟悉 `cmake`。其次,`cmake`对于IDE没有依赖几乎所有的主流 `C/C++ `IDE都支持利用 `cmake `管理 `C/C++`项目。我这次的推荐IDE是 `VSCode `,如果使用 `cmake`进行项目的管理,只需要安装一个插件就可以进行开发了,避免了很多麻烦的问题。
### Git
本次开发中老师提供了 `gitlab`作为代码托管平台,因此在开发过程中我们顺理成章的采用 `Git`作为版本管理的工具,~~虽然组里的同学完全不会。~~
为了避免对于 `Git`的学习占用了过多的开发时间,我没有在项目开始之前花费大量的时间指导他们学习 `Git`,而是再讲解了基本的 `Git`操作流程,比如 `commit push pull`之后就直接开始项目的开发,让大家在开发项目的过程中逐渐熟悉这个工具的使用,在工作中遇到问题再解决对应的问题。同时为了避免合并冲突等比较复杂的情景在早期出现,在最开始开发的时候我让大家都在不同的文件上工作,在后期必须要在同一文件上工作时再来解决合并的问题。
> 我一直以为,在开发的过程中学习才是进步最快的方式
而且采用 `Git`还有一个好处,采用 `Github``Insight`功能可以轻松的看出大家的贡献值()。
![img](1.png "贡献")
## 一些技术上的收获
### 面向对象永远的神
在这次的开发过程中核心版要求完全使用C语言进行开发而在动画版中则可以采用C++进行开发。在编写动画版的代码时,我没有简单的重用核心版的代码,而是利用面向对象的方法完全重写了一遍,虽然重写耗费了我不少的时间,但是在重写了之后,程序中不再使用全局变量;控制公交车通过抽象为三个虚函数,不同的策略对这三个虚函数进行不同的实现来达到不同的调度效果,这样核心的控制流只用编写一遍,个人认为优于核心版中几种策略的控制流虽然大体相似但是在细节上均有不同。
```cpp
/**
* 获得当前公交车应该前进的方向
* @return 公交车前进的方向
*/
virtual int GetBusDirection() = 0;
/**
* 获得公交车在当前指定的策略下应该处理的请求
* @return 请求指针
*/
virtual bus_query_t *GetTargetQuery() = 0;
/**
* 获取公交车现在可以顺便处理的请求
* @return 请求指针
*/
virtual bus_query_t *HandleBTWQuery() = 0;
```
> 然而我还是没有对象
### Qt
具体参见[初学Qt的一点小笔记](https://rrricardo.top/blog/2022/07/01/qt-learning/#more)`QProperyAnimation`那个的多重继承是真的惊艳到我了,感觉在 `C++`这样复杂又精妙的语言面前我还有很多可以学习的地方。
### 单元测试
在这次的开发过程中我引入了 `Google Test`单元测试框架以进行单元测试,虽然并不是所有的模块都编写了对应的测试集,但是单元测试的引入真的帮助我们在开发初期解决的很多的小问题。
```cpp
TEST(rail, CreateRails)
{
rail_node_t *head = CreateRails(10, 10);
rail_node_t *p = head;
for(int i = 1; i <= 10; i++)
{
EXPECT_EQ(p->id, i);
EXPECT_EQ(p->next_node_distance, 10);
EXPECT_EQ(p->last_node_distance, 10);
p = p->next_node;
}
p = head->last_node;
for(int i = 10; i >= 1; i--)
{
EXPECT_EQ(p->id, i);
EXPECT_EQ(p->next_node_distance, 10);
EXPECT_EQ(p->last_node_distance, 10);
p = p->last_node;
}
}
```
### 脚本
在开发的过程中总有一些重复性的简单工作,这时 `Python`这些脚本语言的妙处就展示出来了。由于核心版是采用线上的OJ平台进行测试在提交的时候代码为单文件于是我编写了一个[脚本](https://github.com/jackfiled/auto_bus/blob/master/main.py)来帮助我完成这个工作。

BIN
YaeBlog/source/big-homework/1.png LFS Normal file

Binary file not shown.

View File

@@ -0,0 +1,457 @@
---
title: 建立博客过程的记录
typora-root-url: 建立博客过程的记录
date: 2022-04-08 11:52:32
tags:
- 技术笔记
---
# 建立博客过程的记录
## 博客之始
当我已经在Python的浩瀚大海遨zhengzha了半个暑假后我决定尝试一下传说中程序员专用的学(zhuang)习(bi)手(fangfa)段(fa)——建立自己的个人博客。作为一个半懂不懂的Python程序员心中冒出的第一个想法自然是采用Python的Django作为开发自己的个人博客的手段。然而在阅读了[用Django搭建个人博客](https://www.dusaiphoto.com/article/2/)等的其他人搭建这类动态博客的过程记录之后我便义无反顾的转向了采用javascript开发的博客框架[Hexo](https://hexo.io)<del>说好的Python信仰呢</del>。无他,唯简单尔。
<!--more-->
## 安装需要的程序
### 安装javascipt的运行环境
Hexo作为一个基于javasrcipt的博客框架第一步自然是安装运行Javascript的环境。
Node.js就是几个基于Chrome V8引擎的Javascript运行时环境。这是一个异步事件驱动的Javascript运行时环境。同时Node还带有一个和`pip`功能类似的包管理工具`npm`,使我们可以方便的安装其他人开发的功能扩展包。我们就使用这种方便的方式安装`hexo`
访问[node.js官方网站](https://nodejs.org/en/)下载了node.js的14.17.4 LTS版本的安装包下载完成后安装。在Powershell中输入
```
node -v
```
若能显示出node的版本
```
v14.17.4
```
便说明node.js安装成功。
再输入
```
npm -v
```
显示出npm的版本
```
7.20.3
```
便说明npm也安装完成。
>这里要特别说明npm的更新快于node可能在不久之后npm的版本就不是7.20.3了
>
>同时可以使用`npm install -g npm`方便的升级npm
### 安装Hexo
在Power shell中输入
```
npm install -g hexo-cli
```
>这里的-g代表global即为全局安装Hexo如果像我一样初次使用npm建议安装所有的包时都加上-g。
npm的默认安装源在国外如果在安装过程中遇到网络问题可以像我们使用其他的包管理器一样换为国内源进行安装。在国内比较出名的npm镜像源是由部分淘宝程序员维护的淘宝源。
> 2022年淘宝源的域名由https://npm.taobao.org更改为https://npmmirror.com。
#### 临时使用淘宝源作为下载方式
在利用npm安装npm包时使用
```
npm --registry https://registry.npmmirror.com install
```
可以在本次下载包时采用淘宝源作为下载地址。
#### 将下载地址设置为淘宝源
```
npm config set registry https://registry.npmmirror.com
```
这样设置以后,每次下载包时都会从淘宝的服务器下载。
#### 使用cnpm下载
cnpm是国内一些热心于开源的程序眼开发的一个node包作用和node.js自带的npm完全一样不过默认使用淘宝源下载。在下载cnpm之后就可以方便的在国内源和国外源之间切换当使用国内源时使用
```bash
cnpm install
```
使用国外源时使用
```
npm install
```
这就避免了在需要使用国外源时来回切换的麻烦。<del>虽然我应该不会用到国外源</del>
开始时使用
```
npm install cnpm -g
```
安装cnpm
然后使用
```
cnpm install Hexo-cli -g
```
安装Hexo博客框架。
再输入
```
hexo -v
```
验证安装是否完成。
我这里的输出是
```
hexo-cli: 4.3.0
os: win32 10.0.19043
node: 14.17.4
v8: 8.4.371.23-node.76
uv: 1.41.0
zlib: 1.2.11
brotli: 1.0.9
ares: 1.17.1
modules: 83
nghttp2: 1.42.0
napi: 8
llhttp: 2.1.3
openssl: 1.1.1k
cldr: 39.0
icu: 69.1
tz: 2021a
unicode: 13.0
```
## 初次使用Hexo
### 创建博客
进入一个我们准备用来设置博客的文件夹,在终端中输入
```
Hexo init blog
```
Hexo会以blog为名称创建一个博客文件夹这个文件夹的内容为
![文件夹截图](1.png)
`node_modules`文件夹是Hexo需要用到的一些npm依赖包的存放地址`public`文件夹下是由Hexo渲染产生的静态博客文件`scaffolds`文件夹是博客用到的模板文件,在默认情况下应该有`draft.md`,`page.md`,`post.md`三个模板文件。`themes`是Hexo中可以使用的主题文件。主题也是Hexo一个非常方便的设计我们可以方便使用其他人编写的Hexo Themes让自己的博客在不同的风格之间变换。`source`文件夹就是存放我们写作的博客的地方。一般这里面会有两个子文件夹,`_draft`, `_posts`。我们在里面在创建一个`img`文件夹,把自己的头像图片和网站的图标文件都放在里面,在之后的设置的时候使用。
在终端中输入
```bash
hexo server
INFO Validating config
INFO Start processing
INFO Hexo is running at http://localhost:4000/ . Press Ctrl+C to stop.
```
会在本地运行Hexo自带的一台静态博客服务器。我们用浏览器访问http://localhost:4000, 就可以看见Hexo博客的初始界面
![初始截图](2.png)
这便说明安装成功了,~~可以开香槟了~~
### 写作
在终端中输入
```bash
hexo new "文章标题"
```
> 我已经在设置中设置,不指定模板是自动生成草稿。具体设置见下一节。
然后就会在前面提到的`_draft`文件夹下创建一个markdown文件和一个同名的资源文件夹在资源文件夹下放置在文章中会用到的图片。接下来使用一款适合自己的markdown编辑器就可以开始文章的写作了。
> 我使用的markdown编辑器是[Typora](https://typora.io/),但是这个软件在更新到正式版之后就开始收费了,不过我们可以在[这里](https://typora.io/releases/all)找到版本小于1.0.0的beta版本使用。
为了方便的在写作时插入图片,我下载安装了`hexo-asset-image`这个Hexo插件但是由于这个插件总是在我的电脑上犯病我自己做了一点修改放在了[我的github上](https://github.com/jackfiled/hexo-asset-image)。
通过
```bash
npm install git+https://github.com/jackfiled/hexo-asset-image --save
```
来安装我修改之后的包。
这样在typora中写作的时候先通过格式-图像-设置图片根目录为hexo自动生成的资源文件夹在需要插入图片时通过
```markdown
![example](example.png)
```
这种方式来插入图片,其中`example.png`图片在资源文件夹下。这样在typora中可以正确显示在hexo渲染出来的网页中也可以正确的显示。
在完成写作之后,使用
```bash
hexo publish "文章标题"
```
将文章发布把markdown文件和资源文件夹从`_draft`文件夹移动到`_post`文件夹。
这时使用
```
hexo server
```
就可以看见我们完成的博客文章了。
### 设置主题
为了选择一个恰当而合适的主题,以期避免可能引起的一些不必要的误会和不便,我们设立一个跨部门的多方委员会,用以充分考虑各方的意见,同时选择专门的专家主持流程严谨的研究,充分考虑科学界的意见。通过多次多方的协调会议,在完全理解各方需求的之后,委员会提供了多种选择以供我们选择。
> 汉弗莱附身了属于是
简而言之,我看了几个博客,下载了几个主题测试,然后选择了[yilia-plus](https://github.com/JoeyBling/hexo-theme-yilia-plus)。我比较看重的这个主题的原因是他比较简洁。
在blog文件夹中的themes文件夹`git clone`我们选择好的主题在blog文件夹下的`_config.yaml`中设置主题
```yaml
theme: yilia-plus
```
然后我们在运行
```bash
hexo server
```
就可以看见我们的主题设置已经生效。
### 调整设置文件
Hexo在一般情况下有两个配置文件我们会经常用到blog根目录下的`_config.yaml`, 我们下载的主题文件夹下的`_config.yaml`
#### Hexo的设置
```yaml
# Site
title: Ricardo的博客
subtitle: '奇奇怪怪东西的聚居地'
description: ''
keywords:
author: Ricardo Ren
language: zh-CN
timezone: ''
```
第一部分的网站设置部分,根据自己的需求修改
```yaml
# URL
## Set your site url here. For example, if you use GitHub Page, set url as 'https://username.github.io/project'
url: http://rrricardo.top/blog
permalink: :year/:month/:day/:title/
permalink_defaults:
pretty_urls:
trailing_index: true # Set to false to remove trailing 'index.html' from permalinks
trailing_html: true # Set to false to remove trailing '.html' from permalinks
```
第二部分在url的地方填写自己的博客的地址。
第三部分`Directory`中我没有修改任何玩意儿。
第四部分`Writing`中我把默认使用的模板设置为草稿, 再将`post_asset_folder`设置为true,这样在使用`hexo new `命令使就会再md文件所在的目录创建一个同名的资源文件夹把我们文章中会使用到的图片放在里面。
```yaml
default_layout: draft
post_asset_folder: true
```
剩下的大部分我们就可以不用修改了。
#### yilia-plus的设置
> 由于这个主题是国人开发的,配置文件都有详细的中文注释,按着注释走就完事儿了。
## 将博客部署到云服务器
### 设置deploy
Hexo做为一个静态的博客框架可以将整个博客网站直接渲染为静态页面,我们可以执行
```
hexo g
```
Hexo就会在`public`文件夹下生成整个博客的静态界面,我们只用在服务器上放置这些文件就可以了。
这里使用hexo提供的deploy功能来简化本地同步到git仓库的过程。
在终端执行下列命令安装git部署插件
```bash
npm install hexo-deployer-git --save
```
在根目录下的`_config.yaml`中设置
```yaml
# Deployment
## Docs: https://hexo.io/docs/one-command-deployment
deploy:
type: git
repo: git@gitee.com:ricardo-ren/blog-deploy.git
branch: master
message: Site Update {{now('YYYY-MM-DD HH:mm:ss')}}
```
设置中的message信息可以按自己的喜好设置。
> 如果使用这种方式记得先在git上创建远程仓库
设置完成后执行
```bash
hexo deploy
```
可能会提示没有设置用户名和邮箱
```bash
cd .deploy_git
git config ...
```
这里进入的`.deploy_git`实际上就是git仓库在本地的位置。
### 服务器clone
在服务器上适当的位置执行
```bash
git clone git@gitee.com:ricardo-ren/blog-deploy.git
```
这里将作为博客网站的根目录。
### nginx设置
在云服务器上我使用nginx作为反向代理服务器。由于nginx也是一个不错的静态资源服务器hexo博客也就用nginx作为服务器了。
首先安装nginx
```bash
sudo apt install nginx
```
然后编写nginx的配置文件在`/etc/nginx/nginx.conf`
```nginx
user root;
worker_processes auto;
pid /run/nginx.pid;
include /etc/nginx/modules-enabled/*.conf;
events {
worker_connections 768;
# multi_accept on;
}
http {
##
# Basic Settings
##
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
types_hash_max_size 2048;
# server_tokens off;
# server_names_hash_bucket_size 64;
# server_name_in_redirect off;
include /etc/nginx/mime.types;
default_type application/octet-stream;
##
# SSL Settings
##
ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3; # Dropping SSLv3, ref: POODLE
ssl_prefer_server_ciphers on;
##
# Logging Settings
##
access_log /var/log/nginx/access.log;
error_log /var/log/nginx/error.log;
##
# Gzip Settings
##
gzip on;
# gzip_vary on;
# gzip_proxied any;
# gzip_comp_level 6;
# gzip_buffers 16 8k;
# gzip_http_version 1.1;
# gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;
##
# Virtual Host Configs
##
#这两行我注释了,否则配置文件貌似不会生效
#include /etc/nginx/conf.d/*.conf;
#include /etc/nginx/sites-enabled/*;
# server
server {
listen 443 ssl;
server_name rrricardo.top;
# ssl settings
ssl_certificate /etc/letsencrypt/live/rrricardo.top/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/rrricardo.top/privkey.pem;
include /etc/letsencrypt/options-ssl-nginx.conf;
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
location / {
return 301 https://rrricardo.top/blog/;
}
location /blog/ {
root /home/rcj/website/;
index index.html index.htm;
}
}
server {
listen 80;
server_name rrricardo.top;
return 301 https://$server_name$request_uri;
}
}
```
nginx大部分的默认设置都没有改动指设置了Let's Encrypt提供的HTTPS证书以提供HTTPS服务博客网站挂载在443端口的`/blog/`下当访问443端口的`/`时会301重定向到`/blog/`上。
> 安装Let's Encrypt的服务主要参考[Let's Encrypt](https://letsencrypt.org/zh-cn/getting-started/),[Certbot Instructions | Certbot (eff.org)](https://certbot.eff.org/instructions?ws=nginx&os=ubuntufocal),还有[免费 https 证书Let's Encrypt申请与配置 - 知乎 (zhihu.com)](https://zhuanlan.zhihu.com/p/21286171)。
### 网站备案
按照你的云服务器提供商的指南进行就可以了,我的备案过程还算比较顺利。
## 后记
从2021年9月15日博客仓库的首次提交到这篇博客完成已经过去了七个月的时间经过七个月不断的修补和改进我的博客终于也算是有了一个博客的样子。
一路上读了许多人的博客,已经无法一一指出,在此一并表示感谢。
文中也不免有许多疏漏之处,因时间飞逝,当时遇到的一些问题也无法一一记录,还请诸位读者海涵。

Binary file not shown.

Binary file not shown.

View File

@@ -0,0 +1,108 @@
---
title: C项目中有关头文件的一些问题
tags:
- 技术笔记
- C/C++
typora-root-url: c-include-problems
date: 2022-05-08 11:35:19
---
最近在完成一门`C`语言课程的大作业,课设老师要求我们将程序分模块的开发。在编写项目头文件的时候,遇到了一些令本菜鸡大开眼界的问题。
<!--more-->
## 头文件相互包含问题
### 问题
我项目的结构大致如图所示:
![](1.png)
`include`的头文件目录下有两个头文件,`rail.h``bus.h`,这两个头文件分别定义了两个结构体`rail_node_t``bus_t`
但在这两个结构题的定义中,我互相使用了指向对方结构体的指针。
```C
/*rail.h的内容*/
#include "bus.h"
struct {
...
bus_t *bus;
...
} rail_node;
typedef struct rail_node rail_node_t;
```
```C
/*bus.h的内容*/
#include "rail.h"
struct {
...
rail_node_t* rail_node_pos;
...
} bus;
typedef struct bus bus_t;
```
于是在编译的时候,编译器就会报`rail_node_t``bus_t`这两个结构体未定义的错误。
### 解决
这个问题解决起来也非常的容易,只要修改其中一个结构体的定义就可以了。在以后的设计中注意不要出现这类相互包含的结构体。
> 而且一般这种时候虽然IDE的静态检查不会报错但是自动补全却会失效。所以当你发现你的IDE出现一些奇怪行为的时候就要格外小心了。
## 自己定义的头文件和内部头文件命名冲突的问题
### 问题
在项目中我引入了谷歌的单元测试框架[GTest](https://github.com/google/googletest)。但是在编译测试程序的时候遇到了一些困难。
项目的`test`文件夹下是单元测试文件夹,但是在编译的时候会报错
![](2.png)
大意就是在一个google test内部的头文件中有几个函数找不到定义这个函数都位于`io.h`这个头文件中。
在一开始我以为是平台的兼容性问题但是在我电脑的其他项目中引用这个库都没有问题。在一开始我以为是google test作为一个为`C++`设计的单元测试库在我的`C`项目中出现了不兼容的情况,于是我在设计一个假的单元测试
```C++
#include "gtest/gtest.h"
#include "gmock/gmock.h"
using ::testing::Return;
using ::testing::AtLeast;
using ::testing::Exactly;
using namespace testing;
TEST(test, test)
{
EXPECT_EQ(1, 1);
}
```
不测试任何我编写的库,而只是验证单元测试框架是否能正确运行。但是这个单元测试仍然无法通过编译,报错和之前的一样。
于是我便打开了编译中出错的`gtest-port.h`文件,发现在预处理的过程中头文件的替换出现了问题:在我自己的头文件中也有一个名叫`io.h`的头文件,负责项目中的输入输出,而在预处理的过程中预处理器用这个头文件代替了标准库中的`io.h`,但在我自己的头文件中自然没有测试库需要的函数了。
> 在找bug的过程中还有比较玄学的事情如果我把我库里的头文件一个个的添加就可以编译成功但是如果在第一次编译成功之后再次`cmake ..`,重新生成编译文件,再编译就失败了。这个玄学现象让我迷惑了很久。
### 解决
重新命名模块即可。在后续的模块设计中注意命名。
> 这里还有一个小插曲不要轻易相信IDE提供的重构功能。在这里`CLion`这个IDE就在我重命名头文件的时候把`gtest-port.h`中对`io.h`的引用也重构了。真是智能!~~此处应有流汗黄豆~~
## 后记
只有在实际的开发中才能学到这些教训啊!

Binary file not shown.

Binary file not shown.

View File

@@ -0,0 +1,390 @@
---
title: 编译MediaPipe框架
tags:
- C/C++
- 动作捕捉
date: 2022-11-11 22:20:25
---
# 编译MediaPipe框架
<!--more-->
最近开始研究自己的大创项目,一个关于动作捕捉的小玩意儿,第一步就是~~抄袭开源代码~~借鉴他人优秀成果。在众多的项目中我看上了这个Google开源的优秀框架先把这个项目在本地上跑起来再说。这篇文章就记录了我编译这个框架的过程。
> 在我写完这篇文章之后,我就从`WSL`润到了`Arch Linux`,然而我还是有编译`MediaPipe`的需求,所以这篇文章就增加了`Arch Linux`下编译`MediaPipe`的过程。
首先是在`Arch Linux`下编译的过程。
## 编译环境概述
使用`Arch Linux`,需要注意的是`Arch Linux`采用滚动更新,目前的安装方法可能在不久的将来就不适用了。
## 编译
### 环境准备
首先安装`bazelisk`,由于我安装了`pnpm`,直接使用`pnpm install -g @bazel/bazelisk`安装。
然后使用`pacman`安装:
```shell
sudo pacman -S opencv ffmpeg jdk-openjdk git
```
还有编译的过程中可能会涉及到`python`中的`numpy`软件包,我由于已经安装了`conda`来管理`python`环境,于是就采用`conda install numpy``base`环境中安装。
克隆`MediaPipe`仓库:
```shell
git clone https://github.com/google/mediapipe.git
```
由于`pacman`仓库中安装的`opencv`版本是最新的`opencv4`,我们需要修改`MediaPipe`中的配置文件来适配,修改`third_party/opencv_linux.BUILD`
```python
# Description:
# OpenCV libraries for video/image processing on Linux
licenses(["notice"]) # BSD license
exports_files(["LICENSE"])
# The following build rule assumes that OpenCV is installed by
# 'apt-get install libopencv-core-dev libopencv-highgui-dev \'
# ' libopencv-calib3d-dev libopencv-features2d-dev \'
# ' libopencv-imgproc-dev libopencv-video-dev'
# on Debian Buster/Ubuntu 18.04.
# If you install OpenCV separately, please modify the build rule accordingly.
cc_library(
name = "opencv",
hdrs = glob([
# For OpenCV 4.x
#"include/aarch64-linux-gnu/opencv4/opencv2/cvconfig.h",
#"include/arm-linux-gnueabihf/opencv4/opencv2/cvconfig.h",
#"include/x86_64-linux-gnu/opencv4/opencv2/cvconfig.h",
# 将下面这行取消注释
"include/opencv4/opencv2/**/*.h*",
]),
includes = [
# For OpenCV 4.x
#"include/aarch64-linux-gnu/opencv4/",
#"include/arm-linux-gnueabihf/opencv4/",
#"include/x86_64-linux-gnu/opencv4/",
# 将下面这行取消注释
"include/opencv4/",
],
linkopts = [
"-l:libopencv_core.so",
"-l:libopencv_calib3d.so",
"-l:libopencv_features2d.so",
"-l:libopencv_highgui.so",
"-l:libopencv_imgcodecs.so",
"-l:libopencv_imgproc.so",
"-l:libopencv_video.so",
"-l:libopencv_videoio.so",
],
visibility = ["//visibility:public"],
)
```
### 编译
跑一下实例中的`Hello, World`
首先设置一个环境变量:
```shell
$ export GLOG_logtostderr=1
```
然后一把梭哈:
```shell
bazel run --define MEDIAPIPE_DISABLE_GPU=1 \
mediapipe/examples/desktop/hello_world:hello_world
```
在第一次编译的时候会下载大量的依赖文件,如果遇到网络错误可以多试几次,~~我试了三次才完成~~。
```shell
Starting local Bazel server and connecting to it...
DEBUG: /home/ricardo/.cache/bazel/_bazel_ricardo/9d4c3ea39592a9aa5075148d2a9caf3e/external/org_tensorflow/third_party/repo.bzl:132:14:
Warning: skipping import of repository 'com_google_absl' because it already exists.
DEBUG: /home/ricardo/.cache/bazel/_bazel_ricardo/9d4c3ea39592a9aa5075148d2a9caf3e/external/org_tensorflow/third_party/repo.bzl:132:14:
Warning: skipping import of repository 'com_google_benchmark' because it already exists.
DEBUG: /home/ricardo/.cache/bazel/_bazel_ricardo/9d4c3ea39592a9aa5075148d2a9caf3e/external/org_tensorflow/third_party/repo.bzl:132:14:
Warning: skipping import of repository 'flatbuffers' because it already exists.
DEBUG: /home/ricardo/.cache/bazel/_bazel_ricardo/9d4c3ea39592a9aa5075148d2a9caf3e/external/org_tensorflow/third_party/repo.bzl:132:14:
Warning: skipping import of repository 'pybind11_bazel' because it already exists.
DEBUG: /home/ricardo/.cache/bazel/_bazel_ricardo/9d4c3ea39592a9aa5075148d2a9caf3e/external/org_tensorflow/third_party/repo.bzl:132:14:
Warning: skipping import of repository 'com_googlesource_code_re2' because it already exists.
DEBUG: /home/ricardo/.cache/bazel/_bazel_ricardo/9d4c3ea39592a9aa5075148d2a9caf3e/external/org_tensorflow/third_party/repo.bzl:132:14:
Warning: skipping import of repository 'com_google_protobuf' because it already exists.
DEBUG: /home/ricardo/.cache/bazel/_bazel_ricardo/9d4c3ea39592a9aa5075148d2a9caf3e/external/org_tensorflow/third_party/repo.bzl:132:14:
Warning: skipping import of repository 'com_google_googletest' because it already exists.
DEBUG: /home/ricardo/.cache/bazel/_bazel_ricardo/9d4c3ea39592a9aa5075148d2a9caf3e/external/org_tensorflow/third_party/repo.bzl:132:14:
Warning: skipping import of repository 'com_github_gflags_gflags' because it already exists.
DEBUG: /home/ricardo/.cache/bazel/_bazel_ricardo/9d4c3ea39592a9aa5075148d2a9caf3e/external/org_tensorflow/third_party/repo.bzl:132:14:
Warning: skipping import of repository 'zlib' because it already exists.
DEBUG: /home/ricardo/.cache/bazel/_bazel_ricardo/9d4c3ea39592a9aa5075148d2a9caf3e/external/org_tensorflow/third_party/repo.bzl:132:14:
Warning: skipping import of repository 'rules_python' because it already exists.
DEBUG: /home/ricardo/.cache/bazel/_bazel_ricardo/9d4c3ea39592a9aa5075148d2a9caf3e/external/org_tensorflow/third_party/repo.bzl:132:14:
Warning: skipping import of repository 'build_bazel_rules_apple' because it already exists.
DEBUG: /home/ricardo/.cache/bazel/_bazel_ricardo/9d4c3ea39592a9aa5075148d2a9caf3e/external/org_tensorflow/third_party/repo.bzl:132:14:
Warning: skipping import of repository 'build_bazel_rules_swift' because it already exists.
DEBUG: /home/ricardo/.cache/bazel/_bazel_ricardo/9d4c3ea39592a9aa5075148d2a9caf3e/external/org_tensorflow/third_party/repo.bzl:132:14:
Warning: skipping import of repository 'build_bazel_apple_support' because it already exists.
DEBUG: /home/ricardo/.cache/bazel/_bazel_ricardo/9d4c3ea39592a9aa5075148d2a9caf3e/external/org_tensorflow/third_party/repo.bzl:132:14:
Warning: skipping import of repository 'xctestrunner' because it already exists.
DEBUG: /home/ricardo/.cache/bazel/_bazel_ricardo/9d4c3ea39592a9aa5075148d2a9caf3e/external/org_tensorflow/third_party/repo.bzl:132:14:
Warning: skipping import of repository 'pybind11' because it already exists.
WARNING: /home/ricardo/Documents/code/cpp/mediapipe/mediapipe/framework/tool/BUILD:184:24: in cc_library rule //mediapipe/framework/tool:field_data_cc_proto: target '//mediapipe/framework/tool:field_data_cc_proto' depends on deprecated target '@com_google_protobuf//:cc_wkt_protos': Only for backward compatibility. Do not use.
WARNING: /home/ricardo/Documents/code/cpp/mediapipe/mediapipe/framework/BUILD:54:24: in cc_library rule //mediapipe/framework:calculator_cc_proto: target '//mediapipe/framework:calculator_cc_proto' depends on deprecated target '@com_google_protobuf//:cc_wkt_protos': Only for backward compatibility. Do not use.
INFO: Analyzed target //mediapipe/examples/desktop/hello_world:hello_world (84 packages loaded, 1747 targets configured).
INFO: Found 1 target...
Target //mediapipe/examples/desktop/hello_world:hello_world up-to-date:
bazel-bin/mediapipe/examples/desktop/hello_world/hello_world
INFO: Elapsed time: 3.962s, Critical Path: 0.31s
INFO: 1 process: 1 internal.
INFO: Build completed successfully, 1 total action
INFO: Build completed successfully, 1 total action
I20230115 20:26:29.880736 47247 hello_world.cc:57] Hello World!
I20230115 20:26:29.880805 47247 hello_world.cc:57] Hello World!
I20230115 20:26:29.880817 47247 hello_world.cc:57] Hello World!
I20230115 20:26:29.880888 47247 hello_world.cc:57] Hello World!
I20230115 20:26:29.880957 47247 hello_world.cc:57] Hello World!
I20230115 20:26:29.881028 47247 hello_world.cc:57] Hello World!
I20230115 20:26:29.881096 47247 hello_world.cc:57] Hello World!
I20230115 20:26:29.881157 47247 hello_world.cc:57] Hello World!
I20230115 20:26:29.881198 47247 hello_world.cc:57] Hello World!
I20230115 20:26:29.881268 47247 hello_world.cc:57] Hello World!
```
### 编译Pose解决方案的Android Archieve
我的需求有一个是在安卓手机上使用`MediaPipe``Pose`解决方案,需要编译出一个`AAR`安卓打包文件。
首先安装需要的依赖,`Android SDK``Android NDK`。这里使用`Android Studio`安装。
然后创建一个`bazel`编译的目标文件:在目录`mediapipe/examples/android/src/java/com/google/mediapipe/apps/`下创建一个文件夹`pose_tracking_aar`,在其中创建`BUILD`文件,写入:
```python
load("//mediapipe/java/com/google/mediapipe:mediapipe_aar.bzl", "mediapipe_aar")
mediapipe_aar(
name = "mediapipe_pose_tracking",
calculators = ["//mediapipe/graphs/pose_tracking:pose_tracking_gpu_deps"],
)
```
使用命令编译:
```shell
bazel build -c opt --strip=ALWAYS \
--host_crosstool_top=@bazel_tools//tools/cpp:toolchain \
--fat_apk_cpu=arm64-v8a,armeabi-v7a \
--legacy_whole_archive=0 \
--features=-legacy_whole_archive \
--copt=-fvisibility=hidden \
--copt=-ffunction-sections \
--copt=-fdata-sections \
--copt=-fstack-protector \
--copt=-Oz \
--copt=-fomit-frame-pointer \
--copt=-DABSL_MIN_LOG_LEVEL=2 \
--linkopt=-Wl,--gc-sections,--strip-all \
//mediapipe/examples/android/src/java/com/google/mediapipe/apps/pose_tracking_aar:mediapipe_pose_tracking.aar
```
如果在编译的过程中提示缺失`dx.jar`这个文件而且你用的SDK版本还是高于31的那可能是SDK中缺失了这个文件可以将SDk降级到30就含有这个文件了。我使用的解决办法比较离奇我是将30版本的SDK文件中的这个文件软链接过来解决了这个问题。
![](compile-mediapipe/2023-01-15-22-05-41-Screenshot_20230115_220521.png)
编译消耗的时间可能比较的长,耐心等待即可。
为了在手机上使用,我们还需要编译出`binarypb`文件从Google的服务器上下载`tflite`文件。
编译`binarypb`的过程比较的简单,编译目标在`mediapipe/graphs/pose_tracking`中,名称是`pose_tracking_gpu_binary_graph`,使用下列指令编译:
```shell
bazel build -c opt //mediapipe/graphs/pose_tracking:pose_tracking_gpu_binary_graph
```
> 在这里Google默认添加了一个`input side packet`打开人体遮罩,如果不需要这个效果,需要删除`mediapipe/graphs/pose_tracking/pose_tracking_gpu.pbtxt`文件中的以下内容:
>
> ```
> # Generates side packet to enable segmentation.
> node {
> calculator: "ConstantSidePacketCalculator"
> output_side_packet: "PACKET:enable_segmentation"
> node_options: {
> [type.googleapis.com/mediapipe.ConstantSidePacketCalculatorOptions]: {
> packet { bool_value: true }
> }
> }
> }
> ```
然后还需要从服务器上下载`tflite`文件,`Pose Tracking`这个解决方案需要两个`tflite`文件,第一个是[pose_detection.tflite](https://storage.googleapis.com/mediapipe-assets/pose_detection.tflite),第二个文件则有三个不同的选择,分别对于解决方案中提供的三个质量版本:
![](compile-mediapipe/2023-01-19-20-20-40-Screenshot_20230119_202008.png)
下载地址是[pose_landmark_full.tflite](https://storage.googleapis.com/mediapipe-assets/pose_landmark_full.tflite)[pose_landmark_heavy.tflite](https://storage.googleapis.com/mediapipe-assets/pose_landmark_heavy.tflite)和[pose_landmark_lite.tflite](https://storage.googleapis.com/mediapipe-assets/pose_landmark_lite.tflite)。
> 下面是原来使用`WSL`编译的过程。
## 编译环境概述
我使用的基于WSL2的Ubuntu 22.04编译。主要是参考官方的[安装文档](https://google.github.io/mediapipe/getting_started/install.html#installing-on-debian-and-ubuntu)。
## 编译
### 环境准备
首先安装两个基础性的包:
```bash
sudo apt install build-essential git
```
然后安装MediaPipe的编译管理工具`bazel`,这里我是通过`npm`安装:
```bash
pnpm add -g @bazel/bazelisk
```
通过运行`bazel version`验证安装成功:
```bash
$ bazel version
Bazelisk version: v1.13.2
WARNING: Invoking Bazel in batch mode since it is not invoked from within a workspace (below a directory having a WORKSPACE file).
Extracting Bazel installation...
Build label: 5.3.2
Build target: bazel-out/k8-opt/bin/src/main/java/com/google/devtools/build/lib/bazel/BazelServer_deploy.jar
Build time: Wed Oct 19 18:22:12 2022 (1666203732)
Build timestamp: 1666203732
Build timestamp as int: 1666203732
```
安装`Miniconda`,再在环境中安装`numpy`。编译中依赖于`Python``numpy`,这里网上的资料汗牛充栋,我就不过多赘述。
在准备玩上面的环境之后,我们就可以用`git`将MediaPipe的源代码克隆下来了。
```bash
git clone https://github.com/google/mediapipe.git
```
### 安装Opencv和FFmpeg
我这里选择的是手动编译安装opencv安装的步骤参考官方的安装脚本但是脚本中的不少内容已经过时。
首先安装必要的依赖库和编译管理工具:
```bash
sudo apt install cmake ffmpeg libavformat-dev libdc1394-dev libgtk2.0-dev \
libjpeg-dev libpng-dev libswscale-dev libtbb2 libtbb-dev \
libtiff-dev
```
> 注意:官方脚本中要求安装`libdc1394-22-dev`这个包,但是按照这篇[回答](https://askubuntu.com/questions/1407580/unable-to-locate-package-libdc1394-22-dev),这个包已经被`libdc1392-dev`取代了。
在临时文件夹中创建一个文件专门用来编译:
```bash
cd /tmp
mkdir opencv
cd opencv/
```
使用`git`下载Opencv的源代码
```bash
git clone https://github.com/opencv/opencv_contrib.git
git clone https://github.com/opencv/opencv.git
```
在仓库中签出到指定的版本分支:
```bash
cd opencv
git checkout 3.4
cd ../opencv_contrib
git checkout 3.4
```
创建编译文件,使用指定的`cmake`参数生成编译文件:
```bash
cd ../opencv
mkdir release
cd release
cmake .. -DCMAKE_BUILD_TYPE=RELEASE -DCMAKE_INSTALL_PREFIX=/usr/local \
-DBUILD_TESTS=OFF -DBUILD_PERF_TESTS=OFF -DBUILD_opencv_ts=OFF \
-DOPENCV_EXTRA_MODULES_PATH=/tmp/opencv/opencv_contrib/modules \
-DBUILD_opencv_aruco=OFF -DBUILD_opencv_bgsegm=OFF -DBUILD_opencv_bioinspired=OFF \
-DBUILD_opencv_ccalib=OFF -DBUILD_opencv_datasets=OFF -DBUILD_opencv_dnn=OFF \
-DBUILD_opencv_dnn_objdetect=OFF -DBUILD_opencv_dpm=OFF -DBUILD_opencv_face=OFF \
-DBUILD_opencv_fuzzy=OFF -DBUILD_opencv_hfs=OFF -DBUILD_opencv_img_hash=OFF \
-DBUILD_opencv_js=OFF -DBUILD_opencv_line_descriptor=OFF -DBUILD_opencv_phase_unwrapping=OFF \
-DBUILD_opencv_plot=OFF -DBUILD_opencv_quality=OFF -DBUILD_opencv_reg=OFF \
-DBUILD_opencv_rgbd=OFF -DBUILD_opencv_saliency=OFF -DBUILD_opencv_shape=OFF \
-DBUILD_opencv_structured_light=OFF -DBUILD_opencv_surface_matching=OFF \
-DBUILD_opencv_world=OFF -DBUILD_opencv_xobjdetect=OFF -DBUILD_opencv_xphoto=OFF \
-DCV_ENABLE_INTRINSICS=ON -DWITH_EIGEN=ON -DWITH_PTHREADS=ON -DWITH_PTHREADS_PF=ON \
-DWITH_JPEG=ON -DWITH_PNG=ON -DWITH_TIFF=ON
```
> 注意安装自己下载源代码的地址修改`-DOPENCV_EXTRA_MUDULES_PATH`的值
> 安装过程中还会下载一系列的依赖包,请注意自己的网络环境
使用`make`指令进行编译和安装
```bash
make -j 16
sudo make install
```
编辑链接器的配置:
```bash
sudo touch /etc/ld.so.conf.d/mp_opencv.conf
sudo bash -c "echo /usr/local/lib >> /etc/ld.so.conf.d/mp_opencv.conf"
sudo ldconfig -v
```
然后进行MediaPipe的目录用脚本进行配置文件的修改
```bash
./setup_opencv.sh config_only
```
## 运行首个例子:
```bash
export GLOG_logtostderr=1
bazel run --define MEDIAPIPE_DISABLE_GPU=1 mediapipe/examples/desktop/hello_world:hello_world
```
在等待一段时间的下载依赖和编译之后,我们可以看见:
```bash
I20221110 22:00:50.899885 14357 hello_world.cc:57] Hello World!
I20221110 22:00:50.899948 14357 hello_world.cc:57] Hello World!
I20221110 22:00:50.899955 14357 hello_world.cc:57] Hello World!
I20221110 22:00:50.899960 14357 hello_world.cc:57] Hello World!
I20221110 22:00:50.899962 14357 hello_world.cc:57] Hello World!
I20221110 22:00:50.899982 14357 hello_world.cc:57] Hello World!
I20221110 22:00:50.900000 14357 hello_world.cc:57] Hello World!
I20221110 22:00:50.900025 14357 hello_world.cc:57] Hello World!
I20221110 22:00:50.900030 14357 hello_world.cc:57] Hello World!
I20221110 22:00:50.900193 14357 hello_world.cc:57] Hello World!
```
如果出现了各种奇怪的报错,那可以执行这条命令重新安装依赖再编译试试:
```bash
bazel clean --expunge
```

View File

@@ -0,0 +1,76 @@
---
title: 计算机系统结构——流水线复习
tags:
- 计算机系统结构
- 笔记
date: 2024-06-12 20:27:25
---
让指令的各个执行阶段依次进行运行是一个简单而自然的想法,但是这种方式执行速度慢、运行效率低。因此一个很自然的想法就是将指令重叠起来运行,让执行功能部件被充分的利用起来,这就是**流水线**。
流水线的表示方法有两种。
![image-20240612184855300](computer-architecture-pipeline/image-20240612184855300.png)
第一种被称作**连接图**,清晰的表达出了流水线内部的逻辑关系。
![image-20240612184949777](computer-architecture-pipeline/image-20240612184949777.png)
> 上图中给出了两个流水线中的概念:通过时间和排空时间。其中通过时间又被称作装入时间,是指第一个任务进入流水线到完成的事件;排空时间则相反,是最后一个任务通过流水线的时间。
第二种被称作**时空图**,通过在图中画出一个指令序列通过流水线的过程表现出流水线的时间关系。
在流水线中,每个功能部件之后需要存在一个寄存器,这个寄存器被称为流水寄存器,其作用为在流水线相邻的两端之间传递数据,并且把各段的处理工作相互隔离。
流水线有着多种分类。
按照等级分:
- 部件级,将处理机中的部件分段相互连接,也称作运算操作流水线。
- 处理机级,将指令的执行过程分解为若干个子过程,就是指令流水线。
- 系统级,把多个处理机串行连接,对同一数据流进行处理,称作宏流水线。
按照完成功能的多倍性:
- 单功能,流水线各段之间的连接固定,只能完成一种功能。
- 多功能,段之间的连接可以变化,不同的连接方式可以完成不同的功能。
其中多功能还能进一步分为:
- 静态流水线,同一时间内,多功能流水线的各段只能按照同一种功能的方式连接。
- 动态流水线,同一时间内,多功能流水线的各种可以按照不同的方式连接,执行不同的功能。
![image-20240612190426368](computer-architecture-pipeline/image-20240612190426368.png)
按照流水线中是否存在反馈回路分类:
- 线性,串行连接,没有反馈回路,每个段只能流过一次。
- 非线性,存在反馈回路。
根据任务流入和流出的顺序是否相同:
- 顺序流水线
- 乱序流水线
流水线的性能指标一般由三个指标衡量:
- 吞吐率,单位时间流水线完成任务的数量,或者输出结果的数量。
- 加速比,同一任务,不使用流水线所使用时间与使用流水线所用时间比。
- 效率,流水线设备的利用率。
![image-20240612192700169](computer-architecture-pipeline/image-20240612192700169.png)
在设计流水线的过程中存在若干问题。
1. 瓶颈问题。当流水线各段不均匀时,机器的时钟周期取决于瓶颈段的延迟时间,因此设计流水线时,应当使各段的时间相等。
2. 流水线的额外开销。由于流水寄存器的延迟和时钟偏移开销,流水线往往会增加单条指令的执行时间,当时钟周期过小时,流水已经没有意义。
3. 冲突问题。数据冲突、结构冲突和控制冲突。
一个典型的五段流水线MIPS流水线
![image-20240612193301372](computer-architecture-pipeline/image-20240612193301372.png)

View File

@@ -0,0 +1,136 @@
---
title: 日用Linux挑战 第0篇
tags:
- Linux
- 随笔
date: 2023-01-15 22:23:08
typora-root-url: daily-linux-0
---
# 日用Linux挑战 第0篇
在将开发重心移到`WSL`上一年之后我最终还是决定完全抛弃Windows转向使用Linux作为我日常使用的主力系统。目前我已经使用Linux作为主力系统一个月了。
<!--more-->
## 开始之前
### 电脑
首先介绍一下用来安装Linux系统的电脑——荣耀的`Magicbook 14`,我今年秋天才购入的轻薄笔记本。
- CPUR7-6800H
- 内存DDR5 6400MHz 16GB
- 硬盘: 西部数据 SN550 1T
> 硬盘为我自行更换,原装的盘被我搞掉盘了(笑)
其他的像网卡啥的我就不一一介绍了,具体的硬件兼容性我后面会专门说明。
### 选择发行版
众所周知选择Linux最重要的一步就是选择一个适合自己的Linux发行版。在正式将Linux作为主力系统之前我使用的比较多的发行版是`Ubuntu`,在`WSL`、服务器和树莓派上我都是使用的它。
不过这次,我选择了`Arch`发行版。虽然这个发行版不像`Ubuntu`一类的发行版提供了开箱即用的使用体验,而且安装`Arch`的过程也很难称作简单,但是经过两年半~~小黑子露出了鸡脚~~的Linux练习之后我对于命令行界面的使用还是比较熟悉了。而且`Arch`还提供了其他一些非常吸引我的点:
- 默认的`Arch`安装是一个极简的操作系统,甚至没有图形化的界面,这就提供了一个非常大的优点——不会有任何预装的垃圾
- `Arch`采用滚动升级模型,尽全力让所有的软件包都保持在最新,而我恰好使用的是比较新的硬件,为了避免出现兼容性的问题,我希望能够使用最新的`Linux`内核和软件~~虽然我实际测试Ubuntu等系统也能正常使用~~
- `Arch`还提供了一个由用户维护的软件安装源——`AUR`,一些没有进入官方软件源的软件可以方便的在这里一键安装,非常的好用,非常的方便
- `Arch`还提供了一份非常详尽的`wiki`文档
### 选择桌面环境
我在Linux系统中长时间使用过的桌面环境有`GNOME``KDE`两种。
我首先安装的是`gnome`这个桌面环境,在使用的过程中常常会遇到桌面卡死的情况,切换到其他的`tty`重启`gdm.service`之后就能恢复,在尝试修复无果之后我就切换到了`KDE`桌面环境,目前用上还算满意。
## Hello, Linux!
### 安装Arch
按照`wiki`上的安装教程安装的过程还算的上是比较的顺畅大概90分钟的时间完成了我的第一次`Arch`安装。
不过在安装的过程中,有些问题需要注意:
- 虽然官方Wiki有着中文翻译的版本但是在参考的时候需要注意查看同英语原文之间有没有滞后的内容`Arch`作为一个滚动更新的版本,安装的方法也常常发生变化。
- 在我下载的安装镜像中的`pacman mirrorlist`文件中并没有大陆常用镜像服务器的地址,需要手动添加。我添加了清华大学和浙江大学两个镜像站的地址。
- 如果没有有线的网络链接,记得在系统中安装联网所需要的程序,比如`NetworkManager`啥的,否则你安装完成之后发现没有办法联网,只能再次从安装镜像启动再安装相关的软件。
### 安装桌面环境
在安装桌面环境之前,先安装显卡的驱动程序。
参考文档,需要安装`mesa``lib32-mesa``vulkan-radeon`三个软件包,其中`lib32-mesa`软件包是对32位程序提供支持的软件包为了安装这个软件包需要打开`multilib`这个仓库,取消`/etc/pacman.conf`这个文件中对于`[multilib]`部分的注释来实现这个功能。
```shell
sudo pacman -S mesa lib32-mesa vulkan-radeon
```
由于使用的是`KDE`桌面环境,这个桌面环境对于`wayland`显示服务器的支持还不算太好,于是首先安装`xorg`显示服务器和显示驱动程序。
```shell
sudo pacman -S xorg-server
```
然后安装桌面和`sddm`显示管理器
```shell
sudo pacman -S plasma sddm
sudo systemctl enable sddm.service
```
重启之后图形界面就可以正常显示了。
#### 桌面环境的美化
都在使用`Arch`了,不折腾一下桌面环境的美化是不可能的。
我目前实现的效果大概长这样:
![](2023-01-12-13-28-38-Screenshot_20230112_132829.png)
颇有一种`Windows``MacOS`杂交的风格。
使用的主题地址为[GitHub - vinceliuice/WhiteSur-kde: MacOS big sur theme for kde plasma](https://github.com/vinceliuice/WhiteSur-kde),添加了一个`Windows 10`风格的开始菜单插件[GitHub - Zren/plasma-applet-tiledmenu](https://github.com/Zren/plasma-applet-tiledmenu),字体是直接从`Windows`下面复制过来的`Microsoft YaHei UI`
> 顺便提一下我发现安装kde主题最快的方式是找到主题的Github仓库`clone`之后安装。这种方法比去折腾那个不好用的主题商店快一万倍。
目前在美观上还存在的缺憾是登录界面和锁屏界面我还没有去折腾,还是默认的样子。
### 安装常用软件
先上一张`shell`的系统概览截图:
![](2023-01-12-13-36-45-Screenshot_20230112_133628.png)
终端模拟器直接使用的`konsole`,目前没有进行改动。
系统中使用的输入法是`ibus`框架下的`rime`输入法,词库不太智能。浏览器使用的`edge`几乎完全复制了我在Windows下的体验邮件客户端我使用的`ThunderBird`,不过没法后台通知;`Markdown`写作使用的是`MarkText`,几乎可以取代`Typora`腾讯在2022年的12月30日发布了新版的`QQ`也算是补上了Linux上一个比较大的短板不过目前的支持还是比较差甚至连收发文件都不支持。至于`office`办公软件,我的需求不是很明显,采用`onedrive``Microsoft 365`在浏览器端基本上解决了。编程方面,`VSCode``Jetbrains`这两个我主力的IDE都能在Linux下正常的工作。在游戏方面上我最近玩的`Hearts of Iron 4`有着Linux原生的版本运行流畅`原神`也在利用一些小手段和`wine`之后,比较流畅的运行起来了,至于`Steam`提供的`Pronton`兼容层,还没怎么用过。
### 发现的兼容性问题
显然目前的Linux也不可能做到尽善尽美。
- 在睡眠之后,电脑没有办法正常的播放声音,应该是内核中对于新硬件的支持问题。
- 指纹识别失效了。`fprint`库上还没有提供对我这个硬件的支持。~~也有可能永远不会提供~~
- 笔记本方面的支持还是有所欠缺,也有可能是因为我的调教还不到位。出现过几次合上盖子之后没有办法唤醒的问题,最后只能强制关机后重启。
## 日常使用一个月
作为一个程序员,`Arch Linux`确实非常适合我使用。还记得在折腾`WSL`的时候,`jetbrains`的IDE写代码的时候bug非常多只有`VSCode`的支持稍微好一点,但是作为一个`IDE`的功能又不是很强大。`WSL`还有着一堆兼容性的问题,我还记得在`WSL`脱离`preview`标志之后,我有好几次一启动`WSL`就蓝屏的经历,属实难忘。
不过使用Linux还是有很多不方便的地方尤其是在国内办公软件的兼容性问题上。虽然很多国产软件都提供了Linux的版本不过一般都是统信UOS或者是麒麟Kylin版本的为了在Arch Linux上运行还需要自己研究一下。在这里我要点名批评"Q*"软件,其从官网上下载的`AppImage`格式的程序文件中还有错误,内附的`qq.desktop`文件中的图片路径竟然是写死`/opt/...`。我的评价是做程序的人还是用点心罢,至少打包完成了还是自己测试一遍罢。
平心而论目前的Linux已经可以成为一个日常使用的操作系统了。虽然仍然不能完全摆脱命令行界面普通用户按照`Windows`下的使用经验来使用还存在一定的困难,但是如果你是计算机相关从事人员而且对游戏没有太大的依赖,`Linux`是一个不错的选择。
不出意外的话,本文将是一个系列文的第一篇。我将定期更新这个系列,记录我在学习和工作中使用`Linux`的体验和感受。

View File

@@ -0,0 +1,80 @@
---
title: 日用Linux挑战第1篇
tags:
- Linux
- 随笔
date: 2023-03-08 22:37:29
---
# 日用Linux挑战第1篇
从去年12月底正式切换到`Linux`开始算起,我日常使用`Linux`已经过去了2个月的时间。在本系列的上一篇文章——[日用Linux挑战 第0篇 - Ricardo的博客](https://rrricardo.top/blog/2023/01/15/daily-linux-0/)中,我讲述了我配置自己的`Arch Linux`的过程,还小小的赞扬了一波`Linux`在近些年来取得的进展。但是在这篇文章中,我将重点指出日常使用过程中遇到的问题和困难。
<!--more-->
## 尝试迁移到Wayland
众所周知,`X11`已经是一个落后和过时的显示协议,目前更新的显示协议`Wayland`正在尝试干掉它,但是由于`X11`长期使用带来的稳定性这种工作并不是那么容易。现在是2023年`Wayland`的工作进展到了何种程度?
我使用`KDE`作为我的桌面环境。`KDE`已经有了基础的`Wayland`支持,在启动界面选择`Wayland`会话就可以正常进入。
虽然在切换到`Wayland`会话之后,除了`KDE` 自带的应用程序,日常使用的大部分应用程序还是运行在`xwayland`之下,例如`edge``firefox`浏览器,`VSCode`等。
`/etc/environment`中设置`MOZ_ENABLE_WAYLAND=1`可以`firefox`切换到`Wayland`会话下,运行正常。
`~/.config/microsoft-edge-stable-flags.conf`添加`--ozone-platform-hint=auto``edge`切换到`Wayland`下,运行正常。
然而存在的问题也不少。
- `sddm`窗口管理器在关机的时候没法正常的关闭导致每次关机都需要等待1分30秒。
而且这是一个`sddm`的问题,从[相关Issue](https://github.com/sddm/sddm/issues/1476)上看,这个问题已经在`master`分支被修复了,只是在相关发行版中还没有修复。
采用切换到`sddm-git`的方式修复了这个问题。
> 而且在`archlinuxcn`仓库里面还有这个包,赞美`archlinuxcn`。
- `ibus-rime`输入法在`Wayland`下的适配也是非常的糟糕,甚至是一种不稳定的糟糕,每次出现的问题都不一样,比如现在的问题就是在`Edge`浏览器下无法使用。
在更换使用`fcitx-rime`框架之后稍微好了一点,至少能用了(
- 部分网站的登录信息丢失。
- 使用`BiliBili`全屏播放视频的时候,只要鼠标移入全屏的范围,画面就会黑屏。可能和我使用双显示器有一定的关系。
- 使用`125%`的整体缩放比例的时候,字体处于一种模糊的状态,看上去很不舒服。
简单的说,我不认为现在`Linux`已经准备好切换到`Wayland`下了。
> 听说最精`Ubuntu 22.04`已经默认使用`Wayland`作为显示协议了,等我有了其他的电脑可以试一试,看看商业公司的加入能不能带来一点转机。
## 使用中发现的问题
### 双屏使用的问题
最近入手了一块2K 75Hz的VA显示屏本来打算美滋滋的使用双屏高效率的~~摸鱼~~学习,结果发现问题实在是非常的一言难尽。
- 我的两块屏幕的分辨率不是完全一致的笔记本自带的屏幕是3:2的2160x1440而新买的显示屏是16:9的2560x1440。这就导致两块屏幕的纵向分辨率是一致的而横向分辨率是不同这点似乎迷惑了`KDE`的相关处理程序,导致两块屏幕各有一个部分显示在另外一块屏幕上~~虽然有点抽象,但是我相信你能够想象出来,如果我再次遇到我一定会补一张图的~~。虽然这个问题通过重新设置`Display configuration`就可以解决,但是真的很好笑。
- 部分程序也会因为上面的分辨率不同而导致部分意料之外的情况。比如原神,不如画面整体被横向压缩而出现一大堆椭圆,就是画面的两端有黑边,导致现在我玩原神都是合上笔记本显示屏玩。
> 看来以后想在`Linux`想使用双屏需要购买两块分辨率完全一致的显示屏。
- 程序在两块屏幕上的显示完全是混乱的。比如我打开`IDEA`,启动界面显示在一块屏幕上,选择项目之后的编辑界面又会出现在另外一块屏幕上。
### Wine`键盘按键不停重复的问题
在某次`sudo pacman -Syu`之后,我遇到一个奇怪的现象——在打原神的时候,如果较长时间的按下某一个按键,那么那个按键就会不停的重复,就像没有弹起一样。例如我按下`W`键较长时间再松开,人物仍然会前进,就像我没有松开一样。
当时我的解决办法是在系统设置里临时关闭了`When a key is held`选项再进行游戏。通过查看`pacman`的更新日志,我以为是`plasma`更新的问题。
在之后的某天中,为了折腾`Wayland`,我把输入法从`ibus`框架切换到了`fcitx5`框架,惊喜的发现这个问题消失了。
那么新的问题出现了:这个问题到底是为啥出现捏?不过本着多一事不如少一事的精神,我选择能跑就行,管它为什么。
## 赞美Kde Connect
作为一个大学牲,在自己的不同设备之间频繁的传送文件自然是家常便饭。在进入`Linux`之前,我几乎都是使用`QQ`在我的手机、iPad和笔记本电脑之间共享文件属于是究极折磨。入境大力拥抱`Linux``KDE`,没想到还有意外收获——`KDE connect`。在手机和iPad和笔记本电脑上安装和互相配对之后不同的设备之间就可以方便的发送和接受文件了。妈妈再也不同担心我传送文件的难题了。
好了下次攒够一波问题和经历在更新新一期Linux日用挑战。

View File

@@ -0,0 +1,93 @@
---
title: 日用Linux挑战 第2篇
tags:
- 随笔
- Linux
date: 2023-07-23 11:44:34
typora-root-url: daily-linux-2
---
# 日用Linux挑战 第2篇
使用`Linux`6个月我成功戒掉了原神。
<!--more-->
## 使用Wayland开启桌面环境
在上一篇[文章](https://rrricardo.top/blog/2023/03/08/daily-linux-1/)我尝试在`kde`桌面环境下使用`wayland`显示协议,当时的尝试虽然失败了,却为我这次迁移到`wayland`打下了良好的基础,例如我将输入法从迁移到`fcitx5`
最近恰好被平铺式的窗口管理器种草又在B站上看见一个动画绚丽的`wayland`合成器——[Hyprland](https://hyprland.org/),当即脑袋一热,就把`kde`干掉,装上了`hyprland`
![img](df4211f6be2724b3b4725f7ce5a4078818844857.jpg)
安装`hyprland`的过程非常舒适,`hyprland`被打包为一个单独的二进制文件,使用`pacman`安装之后直接在`tty`下执行:
```bash
Hyprland
```
就可以打开一个干净到极致的桌面环境——没有图标,状态栏等等传统桌面应该有的一切,只有一张简单的壁纸。然后我就发现我完全不会使用这个桌面,虽然鼠标还是如预期一般出现了,但是没有任何用处,`hyprland`的一切都需要使用键盘启动。在对着`hyprland`8个大字发愣5秒钟之后我便屁滚尿流的滚回了`tty`。虽然文档中说明了在默认的配置文件中使用`win+q`的组合键打开终端,但是默认的终端应用程序是`kitty`,然而这个冷门的终端程序在我的电脑上自然是没有的(虽然我在使用过后觉得这个中断程序秒杀我之前用过的全部终端)。看到简陋但是熟悉的`tty`仿佛见到了亲人,我一波`sudo pacman -S kitty`,一边看着进度条飞涨一边感谢`archlinux`。迅速按下`ctrl+shift+F1`,回到忠诚的壁纸画面,不过这次,轻轻按下`win+q`,一个终端窗口如宿命一般出现!
> 上面因为作者刚考完期末神智有点不正常,还请~~根本不存在的~~读者海涵。
`Linux`下拥有了终端就好办了。首先装上`App Launcher`——没有这玩意儿我似乎就只能从终端里启动应用程序,显然是十二分的不方便。在一番比较之后,我在官方文档中选择了`fuzzel`,看上去挺好看的。
> 本来这里想截一张`fuzzel`的图,但是似乎他们的主页挂掉了(
安装了`App Launcher`之后,至少可以打开浏览器,愉快的复制粘贴安装了。剩下的安装过程就按下不表,基本上按照官方文档的`Useful Utilities`进行,在中间选择自己需要的软件的进行安装。然后便是根据配置文件的说明对于外观和使用快捷键进行调整,以及配置壁纸软件`hyprpaper`和状态栏组件`waybar`。具体的配置文件我都放在了自建的`git`服务器上,可以在[这里](https://git.rrricardo.top/jackfiled/dot-config)查看。
### Wayland软件兼容性
跳槽到了新的`wayland`显示协议,最关心的自然是各种软件是否能在`wayland`下正常的工作。
首先是各种浏览器。在我安装的这段时间里2023年5月`microsoft edge`浏览器是基本不能在`wayland`模式下工作,一进入全屏模式就会自动崩溃退出,这对于日常电脑刷视频的我来说简直不能忍受。幸好,`firefox`浏览器在`wayland`模式下工作正常,不愧是和`Linux`关系最好的浏览器。再通过一系列的测试,`chromium`系列的浏览器在`wayland`下的工作状态都不太好,如果需要在`wayland`环境下使用`chromium`系列的浏览器,建议还是运行在`xwayland`模式下。
然后是各种开发工具。我日常使用的`jetbrains`IDE和`VSCode`都工作正常,虽然是工作在`xwayland`模式下。
各种在学习过程中遇到的工具软件基本上都工作运行良好。当然因为没有设置缩放的问题而导致字体都很小。因为如果在配置文件中设置缩放之后会导致字体发虚。下面的截图就是我将我的2K显示屏设置为150%缩放的效果,~~虽然在截图中的效果不明显~~。目前在常用软件中唯一让我十分不满意的软件是`wps`,使用体验完全无法和`offices`相提并论,目前我正在研究使用`wine`运行`offices`,如果成功了就再水一篇博客庆祝一下。
![image-20230702205919301](image-20230702205919301.png)
> 最新的进展是使用`wine`没法安装学校提供的`office 2021`,同时我又不愿意使用古老的`office`版本,但是我发现一个称作`onlyoffice`的第三方软件蛮好用的,等我试用一段时间再说。
>
> 但是`onlyoffice`的最新版本和`wlroots`合成器似乎有点八字不合,我现在是回退到`7.2.1`版本正常使用,详情见这个[issue](https://github.com/ONLYOFFICE/DesktopEditors/issues/1208)
最后就是各种游戏的兼容性了。原神完蛋了。虽然这和`wayland`关系并不是很大,米哈游自己也罪大恶极,但是我换成`wayland`之后的游戏流畅度下降明显,只能眨眼补帧,在硬顶了几周之后我绷不住退游了。目前还不知道是由于原神本身一坨大便的优化还是`wayland`导致的性能下降。而我在`steam`上的各种游戏工作也不是很正常,尤其是各种需要全屏的游戏,比如`CS:GO`,可能是由于我使用外接屏幕的问题。但是`GalGame`类的游戏就工作正常。
总的来说,这次切换到`hyprland`的使用体验还是非常不错的,平铺式窗口管理器也是提高生产力的利器。
### `Hyprland`仍不完善
有得必有失,`hyprland`乃至于`wayland`目前作为一个桌面环境最大的问题就是相关生态仍不完善。这里的生态甚至都不是指对于`wayland`支持之类的东西,而是像系统设置、锁屏界面、状态栏之类的东西。虽然这样说可能有点对于`hyprland`的要求过高了,但是现在这种东拼西凑的构成一个桌面环境给人的体验不是很好,譬如使用`waybar`作为状态栏,`swaylock`作为锁屏界面,`kwallet`作为密码存储器。其中不少软件还都处于一个十分简陋的阶段,例如`swaylock`仅显示一张图片作为界面,甚至连个输入密码的界面都没有。
`hyprland`对于弹出窗口的支持不是很好,尽管这就是平铺式窗口管理器的设计思想。但是在像`idea`之类的编程工具中,弹出窗口是非常常用的功能,不能正常的显示弹出窗口或者显示的位置不对会导致严重的生产力下降。经过测试,当只使用一个显示屏是,可以正常的进行弹出窗口的显示,但是当链接多个显示器时,弹出窗口的位置就变得奇怪起来。
## `amdgpu`导致的相关问题
从我在这台电脑上安装`Linux`之后,便一直会出现图形界面卡死的问题。具体表现为图形界面停止响应,但是通过`ssh`等仍能正常远程链接,大小写锁定正常,使用`Ctrl+Alt+F3`组合键切换到其他`tty`的方式有一定的概率可以从卡死中恢复,但是也存在一定的可能性只能通过强制重启解决。
通过分析日志中的错误信息,大致锁定一下几个`issue`可能和这个问题有关:
- [random amdgpu hangs](https://gitlab.freedesktop.org/drm/amd/-/issues/2443)
- [flip_done timeout](https://gitlab.freedesktop.org/drm/amd/-/issues/2006)
- [ring sdma0 timeout](https://gitlab.freedesktop.org/drm/amd/-/issues/2220)
同时在`raddit``archlinux forum`上都存在大量的讨论均是怀疑为内核的问题。总结一下这个问题似乎和较新版本的内核和AMD的新`rdna2`显卡有关,同时是否链接外接显示器也有着不同的故障表现。而且,随着`linux kernel`不断的升级,报错信息似乎也在变化,~~虽然因为我的系统日志被自动覆盖,不能提供详尽的日志信息~~。
在某一篇讨论中很抱歉我忘记了具体页面有人指出这可能和内核对于CPU电压的调控有关在切换到AMD新发布的CPU频率调节驱动`amd p-state`之后,这个问题就不再出现了。查询[wiki](https://wiki.archlinux.org/title/CPU_frequency_scaling)可以发现,这个驱动目前并没有默认驱动,而是需要通过添加内核参数的方式启动。我使用`grub`作为启动程序,在配置文件`/etc/default/grub``GRUB_CMDLINE_LINUX_DEFAULT=`末尾添加新的启动参数`amd_pstate=active`,重启之后查看当前驱动:
```
cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_driver
amd-pstate-epp
```
目前我已经启动这个新的驱动程序一周时间了,上述问题没有在出现过。

Binary file not shown.

Binary file not shown.

View File

@@ -0,0 +1,100 @@
---
title: 日用Linux挑战 第三篇
tags:
- 随笔
- Linux
typora-root-url: daily-linux-3
date: 2023-09-04 14:47:46
---
# 日用Linux挑战 第三篇
成也开源,败也开源。
<!--more-->
## 放弃 `Wayland`
### 转向`labwc`
在使用`Hyprland`这个平铺式窗口管理器大概三个月之后,我开始怀疑自己是否真的需要一个平铺式的窗口管理器。
作为一个主打“平铺”式管理的桌面管理器,我却很少同时在一块屏幕上显示多个应用,都是将应用全屏之后在显示,再搭配`Meta+1\2\3`切换不同的`workspace`实现不同应用切换的功能。这让我开始思考,也许,我根本不适合使用一个“平铺式”的窗口管理器。其次,我常用的`IDE`——`IDEA`系列让我遇到了一个极为恶性的`bug`:代码重构的弹出式窗口需要很长的一段时间才能显示出来,其时间甚至足够我去喝口水上个厕所。如果我在上班,那么我肯定不会放弃这个显而易见的摸鱼机会,可惜不是。这个`bug`虽然不致命但是过于恶心,毕竟很好的重构思路被打断真的很想先把鼠标扔出去再把电脑砸了。
然后我就开始研究工作在`wayland`显示协议之下的堆叠式窗口管理器。首先,我惊喜的发现,目前`Linux`下的两大主流的桌面环境都开始默认使用`wayland`显示协议,~~虽然我并不打算将这两个臃肿的家伙请回来~~。打开我们伟大的`Arch Linux Wiki`,打开`wayland`页面,这里已经贴心的为我们整理好了使用`wayland`显示协议的堆叠式窗口管理器:
- `enlightenment`:进入官网一看,对于`wayland`的支持还是“实验性”阶段pass
- `hikari`:针对`FreeBSD`开发pass
- `KWin``KDE`使用的窗口管理器pass
- `Liri Shell`不知为何被我华丽无视pass
- `labwc`:看上去还行,一会试试
- `mutter``gnome`使用的窗口管理器pass
- `wayfire``aur`里面的官方包都不能过编译,这种粪软件还是算了吧
- `weston``wayland`示例合成器总给人一种怪怪的感觉pass
- `wio`:官网连接被标记为`dead-link`pass
首先尝试`labwc`,虽然这个软件在`Github`上只有800多颗星不过作为一个小而精的窗口管理器这个哥们还是比较完美的适配了我的需求虽然遇到诸多的小问题
- 没有提供在启动窗口管理器时设置环境变量的方法,导致只能修改`desktop`文件实现这个功能。
- 设置触控板的自然滚动失败
而且作为基于`wlroots`合成器开发的窗口管理器,可以完美继承我在`Hyprland`下的不少设置,像`waybar``hyprpaper`等等。
### 放弃
从今年五月份被`Hyprland`种草,切换到`Wayland`显示协议时算起,我已经使用了三个月的`Wayland`显示协议。刚刚切换到`labwc`使用没超过一周,我就遇到了在`wayland`下的最大缺陷:`matlab`没法正常的使用——虽然软件主界面还可以正常的打开,但是所有的子窗口都没办法打开。恰好那两天我必须要用`matlab`完成一个作业,我直接一波`sudo pacman -S plasma`润回了`KDE`
虽然这个故事听着可能有点突然,但确实就这么发生了,写作这篇博客时使用的桌面环境已经是`KDE`了。
下面就简单讲讲这次使用`KDE`的美化思路。这次使用`KDE`几乎完全继承了之前的[美化思路](https://rrricardo.top/blog/2023/01/15/daily-linux-0/),其中主要的变化为:
- 使用`kitty`作为终端模拟器
- 使用类似于`Windows`下的任务栏显示模式,而不是只显示图标
- 继承了部分在`Hyprland`下的快捷键
- `Meta+F`全屏应用
- `Meta+W`关闭应用
![](Screenshot_20230904_144149.png)
### Fuck You NVIDIA
`matlab`还不是给予最后一击的东西。当我搞到一台使用NVIDIA显卡的笔记本时真正的噩梦才刚刚开始。首先是驱动作为一个被`FUCK`的公司NIVDIA现在在`Linux`上具有三个不同的驱动程序:`nouveau`开源实现的驱动程序,`nvidia`NVIDIA提供的私有驱动程序`nvidia-open`NVIDIA提供的开源驱动程序其中`nvidia-open`还在积极的开发阶段,显然是被`FUCK`太多推出的产物。
参考`Hyprland`官方文档中对于NVIDIA的支持页面需要安装`nvidia-open-dkms`包再加上几个内核参数。咔咔咔一顿操作之后,期待的等待电脑重启。`Linux`万年不变的启动信息刷过,然后电脑就黑屏了。
作为一个经验丰富的NVIDIA受害者我轻轻一搜就发现这个由于INTEL的内核驱动和NVIDIA内核驱动冲突导致的问题。然而现在不能进系统我不得不紧急学习了一波内核启动参数通过在`grub`中修改启动参数禁用`intel_i915`模块才将系统启动了起来。
装好了驱动,现在开始装桌面环境。很遗憾,默认版本的`wlroots`在NVIDIA驱动下兼容性不佳需要自行修改源代码自行编译虽然有着万能的`AUR`辅助我们,但是好巧不巧,那段时间正好遇到`Hyprland`项目调整文件结构,使用`AUR`编译失败了。于是我不得不手动`clone`下来修改之后手动编译。
历尽千难万险,终于进入了`Hyprland` 的桌面。 本来以为安装完成之后就可以愉快的享gongzuo没想到是折磨的开始。
首先是屏幕闪烁的问题,能明显感觉到屏幕会闪烁,出现的时机是完全随机的。按照`wiki`上的说明,在源代码上打上`patch`之后重新编译安装,没用。文档上还记录了一种“核武器”方式,但是需要修改内核配置和造成功耗提升,不敢试。然后是在`vscode`中遇到“屏幕冻结”的问题。这个问题在频繁上下滚动的时候特别容易出现,具体表现为滚动了但是屏幕上的一部分还是显示滚动之前的内容没有刷新。
上述问题正好发生在我发现`matlab`没法在`wayland`下正常工作的时候,一怒之下我就回到了`KDE`
已经是2023年了`Wayland`仍然是`Linux`桌面环境永远的痛。
## 双系统的奇妙bug
上文中提到我搞到了一台使用NVIDIA显卡的笔记本拥有了**强劲**图形性能怎么能不玩游戏呢。但是`Linux`对于游戏支持程序实在是一言难尽,具体可以查看这个系列前几篇我和原神的相爱相杀。于是我就选择了安装`Windows``Linux`双系统。
由于这台笔记本支持安装多个`m.2`的硬盘位,因此我就将两个系统安装到了两个不同的硬盘中,使用`grub`切换在启动时需要进入哪个系统。
### `iwlwifi`加载失败的问题
虽然安装的过程一帆风顺,但是使用的过程却是波折连连。出现的第一个问题就是`iwlwifi`这个驱动程序在从`Windows`切换到`Linux`的启动过程中会启动失败。使用`dmesg`可以观察到如下的报错:
```
iwlwifi: probe of xxxx:xx:xx:x failed with error -110
```
一通咕狗容易发现这样的一个[bug](https://bugzilla.kernel.org/show_bug.cgi?id=209641#c55),似乎是由于`Windows`使用快速启动造成的。
解决办法或者说“回避策略”有两个:
- 关闭`Windows`的快速启动
- 遇到这个问题了重启`Linux`
于是干掉快速启动。

Binary file not shown.

View File

@@ -0,0 +1,85 @@
---
title: 日用Linux挑战 第四篇
tags:
- Linux
- 随笔
date: 2024/03/09 14:00:00
---
小步快跑,面向未来。
<!--more-->
在上一次更新“日用Linux挑战”之后的六个月时间中我又重新在我的两台电脑上安装了`ArchLinux`。在这一轮新的系统安装中引入了不少令人激动的新技术。
## BTRFS
在所有的新技术中最激动人心便是新的文件系统`Btrfs`作为“面向Linux的现代写时复制文件系统”`Btrfs`致力于在实现高级特性的同时保证对错误的宽容和使用与维护的便利性。
相较于古老但是稳定的`Ext4`文件系统,`Btrfs`对我来说最大的好处便是可以零成本的创建快照,便于在出现错误的时候及时回滚或者直接重装系统。因此,为了方便快照的生成和回滚,我在安装系统时使用**扁平化**的子分区划分方法:即尽力避免出现嵌套的子分区,所有需要快照的分区都处在`/`目录之下:
![Screenshot_20240309_115143](daily-linux-4/Screenshot_20240309_115143.png)
- `@`为根分区,挂载在`/`目录之下,打开写时复制;
- `@home`为家目录分区,挂载在`/home`目录之下,打开写时复制;
- `@swap`为交换分区;
- `@var`挂载在`/var`目录之下,鉴于这下面的文件大多数为生成的数据文件,关闭写时复制;
- `@snapshots`是存储快照的子分区,挂载在`/.snapshots`目录之下,打开写时复制。
在一般情况下上每天对`@home`分区进行快照,存放在`/.snapshots`目录下,每周将当天备份的数据备份到移动硬盘中。
### 使用BTRFS的一些小提示
由于`docker`使用的默认文件系统是`overlay2`文件系统,也是一个支持写时复制的文件系统,而在写时复制文件系统`BTRFS`上再叠一层写时复制文件系统显然不好,而且`docker`官方也提供了对于`btrfs`文件系统的[支持](https://docs.docker.com/storage/storagedriver/btrfs-driver/),因此需要修改`docker`使用的文件系统,按照官方文档操作即可。
对于一些常常修改的文件夹例如`.cache`,可以关闭写时复制。
在通过`SSH`将数据备份到远程服务器时,可以使用`zstd`压缩之后再发送,可以大幅减少需要传送的数据量:
```shell
sudo btrfs send /.snapshots/home@20240225 | zstd | ssh root@remote "zstd -d | btrfs receive /path-to-backup"
```
## Wayland
算起来,我已经和`Wayland`显示协议相爱相杀了整整一年了,从`KDE plasma X``Hyprland`,再尝试小众的`labwc`,最后回到了`KDE plasma X`。而在2024年2月29日`KDE plasma`释出6.0版本,将`Wayland`作为默认的显示协议,我也在第一时间更新了版本并使用`wayland`显示协议。现在,我可以比较确定的说,`Wayland`目前已经达到可用的水平了,而且我还是使用`RTX 3060`显卡。
![image-20240309130329784](daily-linux-4/image-20240309130329784.png)
不过相较于`AMDGPU`可以开箱即用,使用`NVIDIA`启动需要配置如下的模块参数:
```
options nvidia_drm modeset=1 fbdev=1
```
同时`NVIDIA`驱动的版本在`550`以上。如果`NVIDIA`驱动的版本`< 550`,那么就需要在内核参数中配置`nvidia_drm.modeset=1`,因为在之前的`NVIDIA`版本驱动中对于`simpledrm`的支持还不完善,需要通过内核参数禁用,~~而且这是一个`ArchLinux`提供的hack~~。
对于输入法,在使用`fcitx5`输入法并通过`Virutal Keyboard`启动输入法之后,在几乎所有的`Wayland`应用程序中都能够正常的唤起输入法,包括各种基于`chromium`的浏览器和`Electron`应用,不过需要在启动应用时传递如下的参数:
```
--enable-features=UseOzonePlatform
--ozone-platform=wayland
--enable-wayland-ime
```
不过`XWayland`应用程序在使用`NVIDIA`驱动时会存在一个神奇的**同步失败**问题,表现为在`xwayland`中部分控件闪烁,交替显示更新前和更新后的帧,而且这个问题几乎不能被截屏抓到,具体可以见`freedesktop`上的这个[issue](https://gitlab.freedesktop.org/xorg/xserver/-/issues/1317)。虽然这个议题下面有着很长的讨论,还是建议大家完整的看一遍,里面甚至还有:
![image-20240309131750535](daily-linux-4/image-20240309131750535.png)
省流:这个议题讨论了在`xserver`中提供显式同步的协议原语,方便图形驱动程序知道什么时候渲染的帧发生了变化。因此这并不是一个`NVIDIA`驱动程序的问题,而是需要将`Linux`显示协议栈从隐式同步迁移到显式同步。但是相关的工作还在开发过程中,因此解决方法有两个:
- 避免使用`xwayland`应用;
- 自行编译该合并请求[!967](https://gitlab.freedesktop.org/xorg/xserver/-/merge_requests/967),或者使用这个[xorg-xwayland-explicit-sync-git](https://aur.archlinux.org/packages/xorg-xwayland-explicit-sync-git)。
## 安装双系统获得的新知识
在这轮安装过程中,为了保证在极端情况下的可用性,我都是选择了双系统`Windows``ArchLinux`进行安装。但是这也带来了一个问题:`Windows`安装的过程中创建的`EFI`分区只有100M的空间而现在`Linux`内核的大小一般是`14M`左右,而`initramfs`的大小来到了`24M`上下,再加上一个更大的备用`initramfs`~~装不下,怎么想也装不下~~,分分钟撑爆`/boot`分区。
于是,我就在`Arch Wiki`上学到一条新知识:
![image-20240309134847166](daily-linux-4/image-20240309134847166.png)
原来`efi`分区其实只用放`grub`
![img](daily-linux-4/cfd17cff0701a8e8c69fecf247f17fc1-1709963611271-2.jpg)

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -0,0 +1,48 @@
---
title: .net从入门到放弃再到入门
tags:
- 技术笔记
- dotnet
date: 2022-08-21 16:59:08
---
# .net从入门到放弃再到入门
我宣布下面的内容都是我在胡扯。在写了一学期的`Java``Springboot`之后,我的评价是`Java`是什么垃圾东西,`C#`才是永远的神!
~~这是一篇专业的.net劝退指南详细记述了我为啥选择了.net又为啥选择了放弃。~~
<!--more-->
### 开端——WPF桌面应用
~~在今年年初的时候,受到[通知大全](https://squidward.top/)启发我决定编写一款自己的DDL管理应用程序。在一开始我打算先在Windows平台上编写当时我了解到Windows上最正统的桌面应用程序开发方式就是采用微软自家的.net平台开发同时在[知乎](https://zhihu.com)上一群人在吹`C#`在设计上是如何如何的优于`JAVA`,当然在这里没有说他们的观点错误的意思,把我忽悠的一愣一愣的。.net在当时已经有了比较老旧的`WinForms`框架、比较流行的`WPF`框架和最新的`MAUI`框架。~~秉持着中国人中庸的思想潮流~~,我选择了`WPF`图形框架作为我当时开发的框架,从此入了.net平台的坑。~~
> 如今这个桌面端的项目已经基本烂尾,项目开源在[github](https://github.com/jackfiled/PostCalendarWindows),算是警醒后来的我在技术选型时应该更加的慎重
~~说实话,在开发的一开始,我就感觉力不从心。~~
~~第一官方文档好但不完全好。微软虽然提供了本地化过的文档但是有很大比例都是机翻的文档。我觉得吧放机翻的文档还不如直接放英文原文的文档。同时文档的大部分都是API列表一类的参考资料对于初学者来说比较重要的“实用教程”等等部分内容较少虽然文档全面而详细但对于初学者来说并没有很大的帮助。毕竟我们不知道在数以万计的API中哪个才能实现自己的需求。~~
~~第二,国内缺少.net相关的社区氛围。这点也是最为劝退的地方相比于`JAVA`在国内广泛的应用和丰富的社区内容,国内.net和`C#`相关的内容除了在`Unity`游戏开发中还算广泛,其他称得上是乏善可陈。~~
~~在一堆好几年前的博客和半懂不懂的英文文档中沉浮一个月之后,我总算是写出了一个可以运行的成品。随着新学期的到来,以学业繁忙为借口,我停止了这个应用的开发。~~
### 重启——服务器开发
~~在经历了桌面应用的失败之后,我转移了自己的开发重心,开始了移动应用的开发,这次我没有坚持被微软的`MAUI`那八字还没有一撇的技术忽悠进去,选择了`flutter`框架搞开发。有应用自然就得有提供数据的后端,在开发服务器时,我又被微软的`ASP.NET`给“忽悠”了进去。~~
~~平心而论,`ASP.NET`开发的过程比上文中的桌面应用程序的开发还是要顺利不少。毕竟现在采用`B/S`架构的服务更多,个人感觉国内应用这项技术的人也不少,相关的技术资料也就不少,我入门的过程也就流畅许多。~~
~~虽然但是,在开发的过程中劝退的地方也不少。第一是微软自己的版本更迭,尤其是在微软宣布`dotnet core`,将.net开源之后个人感觉国内的开发者似乎不是很感冒还是用着原来的老一套。第二是和现在的技术流行方向不同原本采用`JAVA`搞服务器的开发不太可能再更换语言,第二新入行的开发者也会选择当下流行的`GO`等语言,这就导致在开发中有一种单打独斗的感觉,很难找到人同你合作。~~
### 放弃
~~在坚持学习.net八个月之后我还是决定放弃转向学习`JAVA`。~~
- ~~没人用的技术的技术不要硬刚,即使是好技术也不要。没人用的技术就像一潭死水,只有流动起来,才能孕育生机和活力,否则只能在原地腐烂。~~
- ~~之于我而言,语言不仅仅是开发软件的工具,更是需要计算机相关知识的工具。转向`JAVA`的原因之一就是我目前学习的数据结合课——伯克利的`CS61b`就是采用`JAVA`作为编程语言的。~~
~~虽然我已经决定将我的主力语言转向`JAVA`~~但不得不承认`C#`在语言上的特性还是很不错的,以后我的重心不会放在`C#`上,但是他也不会从的技能树上消失。也许在若干年之后,我的主力语言又变回`C#`了(笑)。
> 全文的最后一句话可能是我现在唯一认同的了

View File

@@ -0,0 +1,318 @@
---
title: 环境配置备忘录
date: 2022-01-15 20:19:39
tags:
- 技术笔记
typora-root-url: 环境配置
---
# 环境配置备忘录
电脑上的环境三天两头出问题,写下一个备忘录记录一下电脑上环境的配置过程。
<!--more-->
> Update1: 2022年9月4日
>
> 重新配置了一遍电脑中的环境,删除了许多不切实际的地方。
## 操作系统
版本Windows10专业版
版本号21H2
操作系统内部版本19044.1949
体验Windows Feature Experience Pack 120.2212.4180.0
> 虽然不知道上面的有什么用,但是还是写一下,没准什么时候就有用了。
## Windows Subsystem for Linux(WSL)
安装WSL的官方文档[链接](https://docs.microsoft.com/zh-cn/windows/wsl/install) 。
输入`wsl -l -v`输出
```
NAME STATE VERSION
* Ubuntu Stopped 2
```
使用的Linux分发版是Ubuntu使用的WSL版本是WSL-2。
## 语言
### Python
前往下载安装Python。
使用下列命令将pip下载换源为TUNA源
```bash
pip config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simple
```
### Java
在[这里](https://www.oracle.com/java/technologies/downloads/)下载JDK ,然后配置相关的环境变量 首先设置JAVA_HOME指向安装JDK的根路径。
然后是CALSSPATH内容是
```
.;%JAVA_HOME%\lib;%JAVA_HOME%\lib\tools.jar;
```
再设置PATH相关变量
```
%JAVA_HOME%\bin;
%JAVA_HOME%\jre\bin
```
在PowerShell中输入
```
java --version
```
返回
```
java 17.0.4.1 2022-08-18 LTS
Java(TM) SE Runtime Environment (build 17.0.4.1+1-LTS-2)
Java HotSpot(TM) 64-Bit Server VM (build 17.0.4.1+1-LTS-2, mixed mode, sharing)
```
输入
```
javac --version
```
返回
```
javac 17.0.4.1
```
确认相关的设置完成 。
#### JAVA_TOOL_OPTIONS
设置一个环境变量`JAVA_TOOL_OPTIONS`
```
-Dfile.encoding=UTF8 -Duser.language=en
```
从而规避中文乱码的问题。
> 其他一些官方文档较为全面,安装不需要复杂配置的编程语言就不再赘述了
## IDE
### VSCode
在[这里](https://code.visualstudio.com/)下载。
#### C/C++时的配置文件
```json
// launch.json
{
"version": "0.2.0",
"configurations": [
{//这个大括号里是我们的‘调试(Debug)’配置
"name": "Debug",//配置名称
"type": "cppdbg",//配置类型cppdbg对应cpptools提供的调试功能可以认为此处只能是cppdbg
"request": "launch",// 请求配置类型可以为launch启动或attach附加
"program": "${workspaceFolder}/bin/${fileBasenameNoExtension}.out",// 将要进行调试的程序的路径
"args": [],// 程序调试时传递给程序的命令行参数,这里设为空即可
"stopAtEntry": false,// 设为true时程序将暂停在程序入口处相当于在main上打断点
"cwd": "${workspaceFolder}/bin/",//程序的工作目录
"environment": [],//环境变量,设置为空
"externalConsole": false,// 为true时使用单独的cmd窗口跳出小黑框设为false则是用vscode的内置终端建议用内置终端
"internalConsoleOptions": "neverOpen",// 如果不设为neverOpen调试时会跳到“调试控制台”选项卡新手调试用不到
"MIMode": "gdb",//指定特定的调试器
"miDebuggerPath": "/usr/bin/gdb",//指定的调试器所在路径
"preLaunchTask": "build"// 调试开始前执行的任务我们在调试前要编译构建。与tasks.json的label相对应名字要一样
}
]
}
```
```json
// setting.json
{
"files.associations": {
"stdio.h": "c",
"xutility": "c",
"stdlib.h": "c",
"math.h": "c",
"cmath": "c"
},
"C_Cpp.errorSquiggles": "EnabledIfIncludesResolve"
}
```
```json
// tasks.json
{
"version": "2.0.0",
"tasks": [
{//这个大括号里是构建的配置文件
"label": "build",//任务的名称
"type" : "shell",//任务类型process是vsc把预定义变量和转义解析后直接全部传给commandshell相当于先打开shell再输入命令所以args还会经过shell再解析一遍
"command": "gcc",//在shell中执行的命令若编译C++改为g++
"args": [//一些传递给命令的参数
"${file}",
"-o",
"${workspaceFolder}/bin/${fileBasenameNoExtension}.out",//这里是生成exe程序的位置因为我自己设置了bin文件夹的位置因此我直接使用绝对路径
"-g",//生成和调试有关的信息
"-Wall",//开启额外警告
"-static-libgcc",//静态链接libgcc
"-lm",//链接一个库文件
"-std=c11", // 语言标准可根据自己的需要进行修改写c++要换成c++的语言标准比如c++11
],
"group": {
"kind": "build",//表示这一组任务类型是构建
"isDefault": true//表示这个任务是当前这组任务中的默认任务
},
"presentation": {
"echo": true,//表示在执行任务时在终端要有输出
"reveal": "always",//执行任务时是否跳转到终端面板可以为alwayssilentnever
"focus": false,//设为true后可以使执行task时焦点聚集在终端但对编译来说设为true没有意义因为运行的时候才涉及到输入
"panel": "new",//每次执行这个task时都新建一个终端面板也可以设置为shared共用一个面板不过那样会出现任务将被终端重用的提示比较烦人
"showReuseMessage": true,
"clear": false
},
"problemMatcher":"$gcc",////捕捉编译时编译器在终端里显示的报错信息将其显示在vscode的问题面板里
},
{
"label": "run",
"type": "shell",
"dependsOn":"build",
"command":"${workspaceFolder}/bin/${fileBasenameNoExtension}.out",//这里是运行生成的程序的命令,同样使用绝对路径
"group": {
"kind": "test",
"isDefault": true,
},
"presentation": {
"echo": true,
"reveal": "always",
"focus": true,////这个就设置为true了运行任务后将焦点聚集到终端方便进行输入
"panel": "new",
"showReuseMessage": true,
"clear": false
}
}
]
}
```
### Jetbrians
使用`Jetbrains Toolbox`来管理电脑上的所有IDE。
## 终端美化
首先在微软应用商店下载安装`Windows Terminal`
### PowerShell美化
前往[oh-my-posh](https://github.com/jandedobbeleer/oh-my-posh)下载这个Powershell的美化工具将安装的位置放进`PATH`环境变量中,在终端中输入
```powershell
oh-my-posh --version
```
确认是否安装成功。
同时将下载下来的主题文件放在一个特定的地方(我这里是`C:\Users\ricardo\Programs\oh-my-posh\themes`在PowerShell的启动配置文件`$PROFILE`中加入下面几句
```powershell
Set-Item env:POSH_THEMES_PATH "C:\Users\ricardo\Programs\oh-my-posh\themes"
oh-my-posh init pwsh --config "$env:POSH_THEMES_PATH/paradox.omp.json" | Invoke-Expression
```
下载[posh-git](https://github.com/dahlbyk/posh-git)这是一个给PowerShell提供Git相关辅助的模块下载完成之后将下列命令添加到`$PROFILE`
```powershell
Import-Module ~\Programs\posh-git\src\posh-git.psd1
```
如果在修改了配置文件之后启动提示运行脚本没有经过签名,可以采用下面这条命令来修改运行脚本的权限:
```powershell
Set-ExecutionPolicy -ExecutionPolicy Bypass -Scope CurrentUser
```
再重新运行配置文件就没有问题了。
![终端预览](6.png)
### PowerShell配置文件
```powershell
# oh-my-posh setup
oh-my-posh init pwsh --config "C:\Users\ricardo\Programs\oh-my-posh\themes\paradox.omp.json" | Invoke-Expression
Import-Module ~\Programs\posh-git\src\posh-git.psd1
# proxy functions
function Set-Proxy {
Set-Item Env:http_proxy "http://127.0.0.1:7890"
Set-Item Env:https_proxy "http://127.0.0.1:7890"
}
function Remove-Proxy {
Remove-Item Env:http_proxy
Remove-Item Env:https_proxy
}
```
### WSL美化
目前我还在使用`bash`,不过使用`oh-my-posh`进行了一定的美化。
同Windows下一致进行`oh-my-posh`的下载和安装,在`~/.bashrc`中添加这样一句配置文件
```bash
eval "$(oh-my-posh init bash --config /home/ricardo/.poshthemes/paradox.omp.json)"
```
### BASH设置
`~/.bashrc`文件的末尾新增
```bash
# oh-my-posh setup
eval "$(oh-my-posh init bash --config /home/ricardo/.poshthemes/paradox.omp.json)"
# proxy function
export hostip=$(cat /etc/resolv.conf | grep "nameserver" | cut -f 2 -d " ")
proxy()
{
export http_proxy = "http://${hostip}:7890"
export https_proxy = "http://${hostip}:7890"
}
unproxy()
{
export http_proxy=""
export https_proxy=""
}
# alias settings
alias python=python3
```
## 其他的小工具
字体:
- [Fira Code](https://github.com/tonsky/FiraCode)
命令行工具
- [dust](https://github.com/bootandy/dust)
- [scc](https://github.com/boyter/scc)
- [tcping](https://github.com/cloverstd/tcping)

Binary file not shown.

View File

@@ -0,0 +1,86 @@
---
title: 原神抽卡研究一
tags:
- 原神
date: 2022-12-31 13:38:19
---
# 原神抽卡研究一
<!--more-->
## 背景
目前在市面上出现了大量以抽奖为核心盈利手段的电子游戏,在这种游戏中,获取游戏中的物品不是明码标价的购买,而是通过参加某种抽奖性质的活动。玩家花费一定金额购买参加活动的机会,每次参加都有一定的概率获得玩家想要获得的物品。在抽奖活动中,游戏设计者还会引入一种被称为 “保底” 的游戏机制:开发者向玩家群体承诺在一定的参加次数之后必然会获得到该物品。例如下面是热门游戏《原神》中获取游戏中角色 “抽奖” 活动的概率公示页面。
![](./genshin-gacha-1/2022-12-31-13-06-36-image.png)
在这个 “抽奖” 活动中,玩家可以得到三种等级的物品,在游戏中分别称为 “五星物品”、“四星物品” 和 “三星物品”。在每次的 “抽奖” 活动中,玩家必定会获得上述三种物品中的一种。为了简化问题的讨论,我们现不区分相同等级不同物品之间的不同,只考虑不同星级物品的获取概率。通过概率公示可以知道:五星物品的 “基础概率” 为0.600%,四星物品的 “基础概率” 为 5.100%;五星物品的 “综合概率” 为 1.600%,四星物品的 “综合概率” 为 13.000%。从一个玩家的角度出发,自然会存在两个问题:
- 什么是“基础概率”,什么是“综合概率”?
- 游戏中的实际概率和公式概率吻合吗?
## 研究方法
在大量的重复实验中,事件 A 发生的频率往往具有稳定性,随着重复实验次数的增加,事件发生的频率逐渐稳定于某个固定的客观的常数。由于大数定理,频率最终会收敛到概率。因此,可以通过大量玩家参与这个 “实验” 的数据来回答上述的问题。
### 数据的获取
一般而言,游玩游戏的玩家只能看见自己过往参加游戏时的记录,但是在一些第三方平台上允许其他玩家主动上传数据并公示给大家。虽然这些第三方平台上数据不能完全保证可靠性,可以通过统计中筛选删除明显错误和容易对结果产生较大影响的数据,即使仍然存在少量的错误数据也不会对结果产生比较明显的影响。这里采用[OneBST](https://github.com/OneBST)从第三方平台 [“非小酋” 网站](https://feixiaoqiu.com)获取的截至 2022 年 7 月 26 日的数据作为数据集。
> 数据可以在[Github仓库](https://github.com/OneBST/GI_gacha_dataset/)中下载。
### 数据的统计和分析
利用 Python 中的 Numpy 和 Pandas 等工具包对获取到的数据进行统计分析,在对获取到的数据进行分析的过程中按照以下的规则排除明显错误和对结果影响比较大的数据:
- 抽卡中多次出现违反“保底”规则的数据例如多次获得“四星”物品的间隔超过10次。
- 数据中应该唯一的字段“gacha_id"大量重复。
- 第一次获得四星或者五星物品。
- 数据本身的错误。
## 结论
### 综合概率的解释
在总共 4842256 次抽卡记录中,获得五星物品的次数为 78493 次,于是:
![](genshin-gacha-1/2022-12-31-15-59-20-image.png)
再计算一下每次参加该活动获得四星物品的平均概率:在总共 5000139 次抽卡中,获得四星物品的次数为 653200
![](genshin-gacha-1/2022-12-31-15-59-42-image.png)
不难发现,在误差允许的范围内,计算出来的平均概率和游戏开发者所公布的 “综合概率” 是相同的。当参与这个游戏足够多次时,获取到五星物品和四星物品的数量就可以用这个概率来估计。
### 抽卡过程的数学描述
为了方便讨论,再次将这个 “游戏” 简化为获得五星物品和不获得五星物品两种情况。那么这个 “抽奖” 游戏是否就能被简化为一个概率为 1.6% 的 n 次伯努利实验?不妨假设每次获得五星物品之间相互独立,这样每次获得五星物品都可以认为是首次获得五星物品,这时参加该游戏的次数就会符合概率为 1.6% 的几何分布,而为了符合保底规则,当玩家在参与到第 90 次时仍未获得五星物品,强制给予玩家一个五星的物品。画出实际数据中得到的图像和按照几何分布得到的图像。
![](genshin-gacha-1/2022-12-31-13-20-46-image.png)
![](genshin-gacha-1/2022-12-31-13-21-11-image.png)
不难发现假设的猜想和实际情况不相符合。在抽数小于 73 抽时,获得五星物品的概率逐渐降低,从 0.6% 左右一直降低至 0.4% 左右。当抽数大于等于 73 抽时,抽到的概率开始上升,在抽数等于 77 抽时达到最大,大约为 10.4%。随后概率开始下降,在第 91 抽时,概率等于 0。
如果在实际得到的概率关于抽数的图上再作出概率为 0.6% 的几何分布的图像前73 抽的概率图像和几何分布的图像几乎吻合。也就是说,该抽奖游戏的前 73 抽就是一个符合 P = 0.6% 的几何分布,从第 73 抽开始 “保底” 机制的修正。这就是游戏开发者口中 “基础概率” 的含义:在该抽奖游戏的前数十抽就是一个概率为 0.6% 的伯努利实验。
![](genshin-gacha-1/2022-12-31-13-24-26-image.png)
从大量的实际数据出发,不难发现游戏开发者的申明同实际情况相吻合。
## 不足和展望
### 获取五星物品相互独立的假设
直到作者开始写作本文之前,作者都没有意识到本文 3.2 节中的所有结论几乎都基于该假设。限于文章的篇幅原因和个人的能力问题,在本文中未对这个假设作出验证。下面给出一种验证该猜想的方法。为验证获得五星物品之间相互独立,可以通过统计方法验证下面的等式成立。
![](genshin-gacha-1/2022-12-31-16-00-10-image.png)
### 展望
在获得概率和抽数之间的相关关系之后,可以将这个抽卡的过程当作一个随机过程进行析,并且求出相关的数学特征。从玩家的角度出发,可以指导玩家使用比较合理的策略参加这个游戏,从而以比较低的代价获得自己心仪的物品。从游戏开发者的角度出发,则有有利于优化自己游戏中的概率设计,吸引更多的玩家参与到游戏中来。

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -0,0 +1,241 @@
---
title: 安装pytorch来有深度的学习
date: 2021-11-13 13:21:53
toc: true
tags:
- 技术笔记
typora-root-url: 安装pytorch来有深度的学习
---
# 深度学习预备篇——安装深度学习框架——pytorch
<!--more-->
## pytorch简介
现在我们正处在人工智能的风口上,虽然话说得好“在风口上,一头猪都能起飞”,但是我们显然没法像猪一样飞起来,但是跑两步,至少装一个可以运行人工智能的环境是可以的,就算没法吃猪肉,也得看看猪跑。
`pytorch`就是一个开源的`python`机器学习框架,主要由`facebook`的人工智能团队开发。这个框架采用类似于`numpy`的张量计算可以使用GPU进行加速有着自动微分系统的深度学习模块。
## 安装pytorch
### conda的简介
我们首先要明确的是,`pytorch`是一个开源的python深度学习库在安装pytorch之前我们得先安装python解释器。可能有人会说安装python解释器难道不是小学二年级的内容吗无非是下载python添加到环境变量再命令行输入python验证安装是否完成三部曲。这难道是很困难的事情吗
可如果我们的在~~生活中~~学习中需要用到多个不同的python环境怎么办安装多个python解释器之后如何在不同的环境中切换而且可能在不同的版本下所用的库的版本还不尽相同这时候我们就需要一个便捷的”环境管理器“来管理你电脑上的python环境了这个管理器便是`conda`。再安装了`conda`之后我们就可以在电脑里创建一个个”独立“的python环境每个环境可以有不同的解释器不同的库。可以说是十分方便了。
> 比如在复现其他人的研究成果的时候,他所用的`pytorch`版本和你的不一样,甚至你们的`python`解释器的版本都不一定完全相同。
> 至少一行命令就可以安装python这已经很香了
> 而且`conda`在安装需要的库时,会自动的分析依赖,可以在一定程度上解决环境总是崩溃的问题。
### 安装conda
在安装`conda`的时候,我们可以选择安装`anaconda`这个Python发行版这是一个致力于简化在科学计算中包管理和部署的发行版。
但是这个的问题在于他过于的全面,而我们只是想要安装自己需要的包,因此我选择`miniconda`这个简化的`conda`安装方式,这个安装包中就只有`conda``python`两个程序。同时可以利用`conda``pip`这两个包管理器安装`anaconda``pypi`这两个包仓库中的所有包。
> 这两者的比较,也可以参看[官方文档](https://docs.conda.io/projects/conda/en/latest/user-guide/install/download.html#anaconda-or-miniconda)
我们访问`miniconda`的[官方网站](https://docs.conda.io/en/latest/miniconda.html) ,下滑找到最新的`miniconda`安装包下载链接Latest Miniconda Installer Links
![](1.png)
按照自己的电脑系统下载相应的安装包就可以了。也不大就50M出头的样子。
下载完成之后,我们运行这个安装包,一路下一步就可以了,一般情况下不会有什么要改动的地方。
安装完成之后,我们就会发现自己的开始菜单里多出来了两个快捷方式,
![](2.png)
在上面的那个快捷方式**Anaconda Prompt**是运行含有`conda`命令的CMD的快捷方式而下面那个**Anaconda Power Shell Prompt**是运行含有`conda`命令的Power shell界面的快捷方式。因为我个人对于power shell更加的熟悉我们就是用下面的那个快捷方式。
这个时候肯定会有人好奇竟然你都用power shell了我们为啥不直接使用系统里已经有了的power shell而要启动这里的这个显得有点奇怪的power shell呢
如果你好奇你可以在系统里的power shell里键入`conda`, 会发现系统会告诉你`conda并不是内部化外部应用程序`,马上又有人会说,这个表示`conda`这个程序所在的位置没有被添加进入系统的环境变量里如果添加了之后就可以在系统的power shell里使用了而且我在安装`miniconda`的时候,还看见了添加到环境变量的选项,只是默认的情况下没有勾选。确实,在默认的状态下,`conda`并不会被添加在环境变量中,因为在`conda`的所在目录下还有`python`,如果你将`conda`添加进入了环境变量,就有可能改变原来了系统自带的`python`解释器。所以在默认情况下`conda`是不会被添加到环境变量中的。不过如果你的电脑中并没有`python`,或者像我一样直接采用`conda`来管理电脑上的`python`环境,也可以直接将`conda`添加在环境变量中,而且在后面我们使用`VSCode`编写代码的时候,我们只有将`conda`添加进入环境变量,才可以直接运行代码。~~当然,大概率还是有其它的办法,只是我太菜了不知道~~
好,我们运行**Anaconda Power Shell Prompt**,打开了这个窗口
![](3.png)
这个窗口的出现就标志着我们已经把`conda`正确的安装在我们的电脑之中了。
### conda的使用
我们很容易发现这个power shell与我们常用的power shell之家最大的不同就是在PS的前面多了一个base这个括号就表示我们目前所处的环境是`conda`自动生成的初始环境(base环境)。
在我安装的时候这个环境的python版本是3.9,一会我们就会在这个环境之中安装我们本文的主角**pytorch**,不过在安装之前,我们先来熟悉一下`conda`,毕竟我们会使用这个包管理器来安装我们需要用到的大部分包。
#### 使用conda创建与删除环境
> 在没有指明的情况下,请在**Anaconda Powershell Prompt**环境中使用以下的命令
```
conda info -e
```
这个命令会展示目前系统中已经创建的环境,输入后的效果:
```
# conda environments:
#
base * C:\Users\ricardo.DESKTOP-N6OVBK5\Programs\miniconda3
py310 C:\Users\ricardo.DESKTOP-N6OVBK5\Programs\miniconda3\envs\py310
```
其中会指出环境所在的文件夹,星号标志当前所处的环境。
> 这里也可以使用`conda env list`
```
conda create --name newev python=3.10
```
使用这个命令来在创建一个新的环境,这个环境的由“--name”之后的内容决定这个环境的python解释器版本由python=决定注意这里的环境只用指定到3.x`conda`会自动寻找这个系列下最新的版本安装。
在创建了一个环境之后,使用
```
conda activate <envirname>
```
来切换到相应的环境,`envirname`是你自己指定的环境的名称。
如果像退出这个环境,回到`conda`的默认环境,使用
```
conda deactivate
```
再使用这个命令之后我们就会回到base环境我们可以通过看PS前面的名字来确认这一点。
#### 使用conda管理自己的库
```
conda list
```
这个命令会展示在在当前环境中安装的包。而且注意,虽然我们使用的是`conda`来管理与安装库但是这并不表示python自带的pip包管理工具就被废弃而且就算你通过pip安装的python库页会被`conda`上面的命令正确的识别到。
```
conda list -n <envirname>
```
使用这个命令来查看指定的环境中安装的包。
```
conda search <pkgname>
```
搜索指定的包的信息,比如我输入
```
conda search numpy
```
`conda`会给我返回
```
Loading channels: done
# Name Version Build Channel
······
numpy 1.21.2 py37hfca59bb_0 anaconda/pkgs/main
numpy 1.21.2 py38hfca59bb_0 anaconda/pkgs/main
numpy 1.21.2 py39hfca59bb_0 anaconda/pkgs/main
```
`conda`就会返回给我们包的版本相关的python版本下载的渠道
```
conda install <pkgname>
```
使用这个命令在当前所处的环境里安装我们所需要的包
```
conda install -n <envname> <pkgname>
```
使用“-n”参数来指定一个环境安装我们需要的包
```
conda update -n <envname> <pkgname>
```
使用这个命令来更新指定的包
```
conda remove -n <envname> <pkgname>
```
使用这个命令删除指定环境中我们所不需要的包
分别使用
```
conda update conda
conda update python
```
来升级`conda``python`
> 注意假设现在python版本是3.5则只会升级到3.5系列的最新版
#### 使用conda的国内镜像源
由于部分原因使用conda的默认镜像源安装我们需要的库可能花费的时间较长或者提示网络连接失败等等。为了解决这个问题我们可以使用清华大学提供的镜像源镜像站提供了相关设置的[帮助文档](https://mirrors.tuna.tsinghua.edu.cn/help/anaconda/),根据文档的指示一步步设置就可以了。
### 使用conda安装pytorch
我们访问pytorch的[官方网站](https://pytorch.org/),我们可以轻松在首页就找到这个表格
![](4.png)
先简单介绍一下这个表格的每一行,第一行是选择我们安装`pytorch`的版本是稳定版预览版还是长期支持版。第二行是选择我们索要下载的操作系统这里就默认大家都是用Windows了第三行是选择我们安装`pytorch`的方式,可以看见有我们刚学习的`conda`,我们很熟悉的`pip`, 还有两种其他的方式。我们选择`conda`。第三行是我们所使用的语言,我们自然选择`python`。然后是第四行“Compute Platform” 如果直译的话是计算平台就是我们选择用来计算的设备。这里就是又一个新的知识点了。一般来说我们在使用电脑时都是使用CPU作为计算的主力显卡GPU)一般只是用来输出图像但在深度学习出现后人们发现显卡原本专精于图形计算的计算力也很适用于深度学习中人工神经网络的计算。为了能够使用GPU的算力而不是让它仅仅输出图像我们就得下载相关的工具这个工具就是CUDA。当然这种比较强大的能力并不是只要下载一个CUDA就可以拥有的~~你还得有钱~~你还得拥有一块英伟达的显卡如果你没有显卡那你就只能老老实实的使用自己的CPU进行计算了在表格的第四行选择CPU。而对于我们~~土豪~~有显卡的同学我们得先确定确定自己电脑上CUDA的版本打开我们的老朋友power shell输入
```
nvidia-smi
```
这是英伟达显卡的一个监控命令可以看见当前GPU的使用情况我们从这里来看自己的CUDA版本。
在我的RTX3060笔记本上输出是这样的
```
Mon Nov 15 10:43:50 2021
+-----------------------------------------------------------------------------+
| NVIDIA-SMI 462.36 Driver Version: 462.36 CUDA Version: 11.2 |
|-------------------------------+----------------------+----------------------+
| GPU Name TCC/WDDM | Bus-Id Disp.A | Volatile Uncorr. ECC |
| Fan Temp Perf Pwr:Usage/Cap| Memory-Usage | GPU-Util Compute M. |
| | | MIG M. |
|===============================+======================+======================|
| 0 GeForce RTX 306... WDDM | 00000000:01:00.0 Off | N/A |
| N/A 49C P0 19W / N/A | 121MiB / 6144MiB | 0% Default |
| | | N/A |
+-------------------------------+----------------------+----------------------+
+-----------------------------------------------------------------------------+
| Processes: |
| GPU GI CI PID Type Process name GPU Memory |
| ID ID Usage |
|=============================================================================|
| No running processes found |
+-----------------------------------------------------------------------------+
```
> 注意:以下内容仅供参考,我只能说,我这样是成功了的,不代表所有人都可以成功
在表格的第一行我们可以看见我电脑上CUDA的版本是11.2,我们回到`pytorch`的官网发现它的表格中只有cuda10.2与cuda11.3两个版本供我们选择,虽然我的电脑上的`cuda`只是112的但是我选择的仍是cuda11.3版本的因为3060貌似是不支持cuda10的了。~~玄学开始了~~我们在表格中选择完之后,就会得到一句命令,把这个命令复制到**Anaconda Power shell Prompt**中去运行,在提示确认的地方回车,就会开始下载安装`pytorch`,我们耐心等待一段时间。
在安装完成之后,我们来到了~~最激动人心的~~验证安装是否成功以及cuda是否能够被正确调用的环节我们首先输入
```
conda list
```
查看当前的环境中是否已经有`pytorch`这个库,一般来说,这一步不会有大问题。
然后我们输入
```
python
```
打开python的交互式解释器输入
```
import torch
```
看看能否正确的导入这个库,这个导入的过程可能有点长,不要紧张
如果这锅过程没有报错的话,就说明导入正常了,我们简单的使用一下这个库来进一步判断,输入
```
x = torch.rand(3,5)
print(x)
```
输出
```
tensor([[0.7280, 0.0764, 0.1278, 0.0408, 0.8655],
[0.8270, 0.2127, 0.1831, 0.0908, 0.6578],
[0.8396, 0.4007, 0.2550, 0.8508, 0.4947]])
```
这里是输出的均是随机数,如果数不一样才正常。
我们在验证一下是否可以调用`cuda`, 输入
```
print(torch.cuda.is_available())
```
如果输出True就是皆大欢喜安装成功如果输出False那~~建议放弃治疗~~我也爱莫能助,毕竟我这一路下来虽然在`cuda`的版本上有点不对劲的地方,但他就是给我返回了
```
True
```
## 写在最后
在安装`pytorch`的这一路下来,我在网上查了无数的资料,似乎在安装`pytorch`的一路上就死了不少的人~~大概是因为他们是在Ubuntu上安装的~~,特别是调用`cuda`的那里。不过我按照[官方文档](https://pytorch.org/get-started/locally/)一路下来,没有出什么大的幺蛾子,只能说希望我自己的经历能对大家有所帮助吧。

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -0,0 +1,141 @@
---
title: 大学生用啥配置——计算机专业
tags:
- 随笔
typora-root-url: laptop-for-computer
date: 2022-06-13 16:17:27
---
# 大学生用啥配置——计算机专业
> 本文是应B站UP主[远古时代装机猿](https://space.bilibili.com/35359510)发起的[大学生用啥配置](https://www.bilibili.com/video/BV1kZ4y1i7Le)公益活动而写
>
> 目前某不知名211大学计算机专业在读
>
> 同时也是给我的许多即将选择计算机专业的同学做一个参考
<!--more-->
## 专业需求
### 操作系统
对于大学生来说,还是一台`Windows`系统的电脑更加的适合,理由如下:
- 在学校中的大多人都是使用`Windows`系统,老师的教学设计也是以同学们拥有一台`Windows`系统的电脑为基础的,如果你在学习过程中遇到了一些`MacOS`系统所特有的问题,可能连可以问的人都没有。
- 在学习过程中可能会遇到一些课程需要使用只有`Windows`版本的软件,如果你购买了一台苹果电脑,遇上这种时候就只能使用学校提供的机房或者是安装虚拟机了。
### 常用软件
目前我经常使用的软件如下所示:
- [VSCode](https://code.visualstudio.com/)微软出品的文本编辑器,是我目前使用最多的软件之一。我用它来写简单的`C/C++`,`Python``latex`等。
- [Visual Studio](https://visualstudio.microsoft.com/zh-hans/vs/)~~宇宙第一IDE~~用来写`C#`
- [PyCharm](https://www.jetbrains.com/pycharm/)用来写比较复杂的`Python`项目。
- [CLion](https://www.jetbrains.com/clion/)用来写大型的`C/C++`项目。
- [WebStorm](https://www.jetbrains.com/webstorm/)用来写网页。
- [Android Studio](https://developer.android.google.cn/studio/)用来开发安卓应用。
- [WSL](https://docs.microsoft.com/zh-cn/windows/wsl/about)在`Windows`系统上使用`Linux`的神器,其实质上就是一个虚拟机,不过需要的性能少于传统的虚拟机。
还有一系列日常软件像`QQ`啥的就不列出了,但凡是台电脑也不至于运行不起来。
> 严格来说我还是有相当多的“常用”软件没有提及像C语言编译器`MinGW GCC`这类的工具不过这类命令行工具对性能的需求不容易体现出来就在下文中对应的IDE处提及了。
### 日常使用场景的列举
> 列举了一些专业学习中常见的一些使用场景,记录了对应性能占用,使文章显得有理有据(确信)
>
> 可直接跳转到分析部分
#### 学习、编写`C/C++`程序
打开`WSL `,`VSCode`和一大堆的网页。
目前的性能占用如图所示
![](c.png)
在编译代码时CPU占用会有一个短时的提升不过由于目前编写的程序都较为简单编译转瞬就完成了。
#### 编写较为复杂的`C/C++`项目
以我目前的C语言大作业为例打开两个`CLion`进行开发,同时打开一大堆网页查资料。
性能的占用如图所示
![](clion.png)
在刚打开项目和编译整个项目时CPU的占用会上升但在完成之后CPU的占用就会回落。
目前项目的代码量在50000+编译整个项目需要15秒左右但是大部分的代码都是引用的库只需要编译一次后续的修改只用编译2~3秒就可以。
#### 编写`C#`项目
通过安装了`Reshaper`插件的`Visual Studio`打开`WPF`应用进行开发,同时也是打开一大堆浏览器标签页查资料。
性能占用如图所示
![](csharp.png)
#### 写网站
打开`WebStorm`编写网站。
性能占用如图所示:
![](web.png)
### 软件的运行需求分析
目前我常用的软件以吃CPU和内存为主对于显卡的需求相对来说不大。
CPU的占用主要出现在打开项目和编译项目上不同CPU的差别主要体现在需要的时间上对于实际的使用不能产生比较的区别~~编译的时间长一点还可以去摸鱼~~。
而对于内存的需求就比较大了目前一般的IDE(集成开发环境)一打开就会吃掉1G以上的内存项目越复杂还可能更大而且在写代码的同时还会打开一大堆的浏览器标签页查看资料和文档众所都周知目前流行的`chrome`浏览器内核在使用内存上是一点都不吝啬因此推荐16G起步。
对于显卡如果不需要在工作之余进行一些手脑协调训练那么亮机卡或者核显就是不错的选择对于写代码的人来说高U低显才是合适的搭配。
之于硬盘写代码对于硬盘的占用也不算是太大代码文件基本上都是文本文件不会占用太多的空间。占用比较大的IDE也一般都在10G以下~~比起一些学习资料小很多了~~一般512G的固态硬盘就完全足够了。
之于屏幕作为大多数的学习活动都在电脑上进行的专业把钱花在一块素质良好的屏幕上是完全值得的。与游戏电竞不同的是在选择屏幕是应该更看重分辨率而不是刷新率刷新率在60Hz就完全足够了如果是笔记本较低的刷新率还有助于降低耗电量增加续航。
## 我用啥配置
作为一名眼脑协调训练热爱者的我目前手持的笔记本自然是一台正宗的游戏本——Dell G15 5511这台笔记本的详细配置如下所示
- i7-11800H
- 16G DDR4 3200
- RTX3060(125W)
- 512G SSD + 1T SSD自行添加
- 1080P 165Hz 屏幕
下面简单谈谈对于我而言,这台电脑的优势和劣势:
### 优势
- 强大的性能使我的游戏体验还是十分不错的
- 有一个硬盘位可以自行扩展以存放学习资料
- 内存不是板载,在后期内存成为瓶颈时可以扩展
- 拥有数量众多的接口
### 劣势
- 离电续航较短,在某次考试中由于没有占到有插座的座位而不得不使用核显+60Hz+低亮度来完成2个小时的考试。
- 旅行重量比较大官方标称重量2.81千克,再加上一块板砖充电器,带着它出门的体验一言难尽,简直是锻炼身体的必备利器。
- 风扇的噪音比较大,在图书馆里使用可能给你带来一些尴尬。
### 优化
> 如果我是今年毕业,我一定选台式机+轻薄本的组合,去年硬件市场的行情打消了我这个蓄谋已久的想法
我目前的打算自己再攒一台锐龙6000系轻薄本出来用否则随着后面专业课程的增加需要用到笔记本的场景只会越来越多如果仍然像现在一样几乎限制在寝室里使用难以为继。毕竟众所都周知啊寝室并不是一个理想的学习环境如果想要沉浸式的学习还是得去图书馆和教室。
## 给后来者的建议
- 如果你不玩游戏,那么一台性能释放较好的核显轻薄本就是你最好的选择。短时间强大的性能释放足够帮你应付编译等场景下的性能需求,轻薄本不错的续航和较轻的重量又能保证你在学校中能够相对自由的移动
- 如果你玩游戏,那么还是顺从自己的内心使用游戏本吧!否则你看见同寝室友愉快玩耍时,也会生出再买一台电脑的念头。
- 如果你不确定或者有点小钱,也可以选择轻薄本加台式机的组合,这也是最让人感到舒适的配置组合,兼具轻薄本的灵活性和台式机的高性能,唯一的缺点是贵,不过那算是我的缺点
- 内存保底16G如果能更大当然更好
- 屏幕素质可以选择的高一些
- 如果你已经确定自己要选购一台台式机,请确保自己未来就读的学校有足够的空间和供电来确保自己可以愉快的玩耍,否则不要买了轻薄本到了学校傻了眼,“这小破地方怎么放台式机啊”,或者是游戏一开全寝断电

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -0,0 +1,56 @@
---
title: 解决云原神无法在Linux中浏览器下运行的问题
tags:
- 生活小妙招
- 原神
date: 2023-10-09 23:56:34
---
# 解决云原神无法在Linux中浏览器下运行的问题
本文为转载`bilibili`用户[@SocialismTeen](https://space.bilibili.com/33027704)在他的[专栏](https://www.bilibili.com/read/cv26576757)中给出的解决办法。
<!--more-->
## 问题
`Linux`平台上使用`Chromium`系列内核的浏览器打开[云原神](https://ys.mihoyo.com/cloud/#/)会发生鼠标无法控制视角的问题。
## 解决
根据上面提到那位同志的研究,该问题是由于云原神在获得鼠标移动时使用的`API`: `Pointer Lock API`。在**其他**平台上该`API`支持名为`unadjustedMovement`的参数以关闭鼠标加速获得更好的体验,但是在`Linux`平台上并不支持该参数,因此程序无法正确获得到鼠标指针的位置。
该同志给出的解决办法为使用钩子函数消除调用该`API`时的参数,使用的代码如下:
```javascript
const origin = HTMLElement.prototype.requestPointerLock
HTMLElement.prototype.requestPointerLock = function () {
return origin.call(this)
}
```
为了获得良好的游戏体验,可以使用[油猴插件](https://www.tampermonkey.net/)在进入网页时自动运行上述脚本:
```javascript
// ==UserScript==
// @name Genshin Cloud
// @namespace http://tampermonkey.net/
// @version 0.1
// @description fix a Genshin Impact cloud game bug
// @match https://ys.mihoyo.com/cloud/*
// @grant none
// ==/UserScript==
(function () {
'use strict';
const origin = HTMLElement.prototype.requestPointerLock
HTMLElement.prototype.requestPointerLock = function () {
return origin.call(this)
}
})();
```

View File

@@ -0,0 +1,150 @@
---
title: 让Minecraft运行在Wayland下
tags:
- Linux
- 生活小妙招
date: 2024-1-12 20:10:06
---
<!--more-->
让Minecraft游戏使用`Wayland`显示协议。
## Update At 2024-2-24
在两天前2024年的2月22日`glfw`释出了一个新版本`3.4`。在新版本中,`glfw`大幅强化了对于`wayland`显示协议的支持,在默认情况下就会直接使用`wayland`显示协议。但是为了能够正常的运行`minecraft`,还需要对源代码进行修改:
```diff
diff --git a/src/wl_window.c b/src/wl_window.c
index 5b491ffb..e96a21e4 100644
--- a/src/wl_window.c
+++ b/src/wl_window.c
@@ -2227,8 +2227,9 @@ void _glfwSetWindowTitleWayland(_GLFWwindow* window, const char* title)
void _glfwSetWindowIconWayland(_GLFWwindow* window,
int count, const GLFWimage* images)
{
- _glfwInputError(GLFW_FEATURE_UNAVAILABLE,
- "Wayland: The platform does not support setting the window icon");
+ // _glfwInputError(GLFW_FEATURE_UNAVAILABLE,
+ // "Wayland: The platform does not support setting the window icon");
+ fprintf(stderr, "!!! Ignoring Error: Wayland: The platform does not support setting the window icon\n");
}
void _glfwGetWindowPosWayland(_GLFWwindow* window, int* xpos, int* ypos)
```
进行编译的命令也需要修改为:
```shell
cmake -S . -B build -D GLFW_BUILD_WAYLAND=1 -D BUILD_SHARED_LIBS=ON -D GLFW_BUILD_EXAMPLES=no -D GLFW_BUILD_TESTS=no -D GLFW_BUILD_DOCS=no
```
在使用`NVIDIA`显卡仍然需要设置环境变量:
```shell
export __GL_THREADED_OPTIMIZATIONS=0
```
虽然在新的版本中`glfw`对于`wayland`的支持有了长足的进展,但是完全支持还需要一定的时间。
## TL;DR
需要手动编译一个依赖库`glfw`,并在编译之前修改源代码:
```diff
diff --git a/src/platform.c b/src/platform.c
index c5966ae7..3e7442f9 100644
--- a/src/platform.c
+++ b/src/platform.c
@@ -49,12 +49,12 @@ static const struct
#if defined(_GLFW_COCOA)
{ GLFW_PLATFORM_COCOA, _glfwConnectCocoa },
#endif
-#if defined(_GLFW_X11)
- { GLFW_PLATFORM_X11, _glfwConnectX11 },
-#endif
#if defined(_GLFW_WAYLAND)
{ GLFW_PLATFORM_WAYLAND, _glfwConnectWayland },
#endif
+#if defined(_GLFW_X11)
+ { GLFW_PLATFORM_X11, _glfwConnectX11 },
+#endif
};
GLFWbool _glfwSelectPlatform(int desiredID, _GLFWplatform* platform)
diff --git a/src/wl_window.c b/src/wl_window.c
index 7b9e3d0d..dd1c89ed 100644
--- a/src/wl_window.c
+++ b/src/wl_window.c
@@ -2109,8 +2109,7 @@ void _glfwSetWindowTitleWayland(_GLFWwindow* window, const char* title)
void _glfwSetWindowIconWayland(_GLFWwindow* window,
int count, const GLFWimage* images)
{
- _glfwInputError(GLFW_FEATURE_UNAVAILABLE,
- "Wayland: The platform does not support setting the window icon");
+ fprintf(stderr, "!!! Ignoring Error: Wayland: The platform does not support setting the window icon\n");
}
void _glfwGetWindowPosWayland(_GLFWwindow* window, int* xpos, int* ypos)
@@ -2353,8 +2352,7 @@ void _glfwRequestWindowAttentionWayland(_GLFWwindow* window)
void _glfwFocusWindowWayland(_GLFWwindow* window)
{
- _glfwInputError(GLFW_FEATURE_UNAVAILABLE,
- "Wayland: The platform does not support setting the input focus");
+ fprintf(stderr, "!!! Ignoring Error: Wayland: The platform does not support setting the input focus\n");
}
void _glfwSetWindowMonitorWayland(_GLFWwindow* window,
```
首先克隆[glfw](https://github.com/glfw/glfw)源代码,并将上述代码保存为`glfw.patch`文件。使用下列指令应用变更并编译`glfw`代码:
```shell
git apply glfw.patch
cmake -S . -B build -D GLFW_USE_WAYLAND=1 -D BUILD_SHARED_LIBS=ON -D GLFW_BUILD_EXAMPLES=no -D GLFW_BUILD_TESTS=no -D GLFW_BUILD_DOCS=no
cd build
make
```
使用`make install`将编译好的库文件安装到`/usr/local/lib`中。
在启动游戏时添加`java`启动参数`-Dorg.lwjgl.glfw.libname=/usr/local/lib/libglfw.so`以使用自行编译的`glfw`库。
尝试运行游戏。如果游戏仍然运行失败并报错为`An EGLDisplay argument does not name a valid EGL display connection`,尝试在运行游戏前设置如下的环境变量:
```shell
export __GL_THREADED_OPTIMIZATIONS=0
```
## 细说
最近将自己手上的`Linux`设备逐渐迁移到`Wayland`显示协议,在使用`AMD`显卡的机器上基本没遇到什么严重的显示问题,在`NVIDIA`却处处都是问题看来老黄确实罪大恶极。本文便是解决Minecraft在`XWayland`上显示时疯狂闪烁的`bug`通过将Minecraft设置为使用`Wayland`显示协议。
可能有人要问的是,`java`上对于`Wayland`的支持不是还没有正式合并到主线吗,`Minecraft`作为一个使用`java`实现的游戏为什么能够使用`Wayland`显示协议呢?这是因为传统意义上`java`对于`Wayland`的支持是指`java`上的图形库对于`Wayland`的支持还没有就绪但是Minecraft作为一个游戏并没有使用这些图形库而是直接和底层的渲染API进行交互的因此可以直接修改底层API让Minecraft使用`Wayland`显示协议。
具体来说Minecraft使用的是一个称作`glfw`跨平台图形库,因此我们只需要修改该图形库让其使用`Wayland`进行显示就可以了。需要做的便是给源代码打上上面给出的补丁,重新编译安装即可。
然后就是设置Minecraft使用我们自行编译的图形库需要设置`java`启动参数,我使用的[hmcl](https://github.com/huanghongxun/HMCL)这款启动器,可以在设置里面很方便的设置启动参数:
![image-20240105212744116](./minecraft-wayland/image-20240105212744116.png)
但是,如果你使用的是`nvidia`显卡,这里还会遇到一个问题:
![image-20240105213439528](./minecraft-wayland/image-20240105213439528.png)
这个问题从一些资料显示仍然是老黄整的好活:
![image-20240105213942445](./minecraft-wayland/image-20240105213942445.png)
设置环境变量解决,再次强烈推荐[hmcl](https://github.com/huanghongxun/HMCL)启动器,可以方便的设置环境变量。
```
export __GL_THREADED_OPTIMIZATIONS=0
```
## 参考资料
- https://github.com/Admicos/minecraft-wayland/issues/54
- https://github.com/Admicos/minecraft-wayland/issues/55
- https://www.mcmod.cn/class/2785.html

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -0,0 +1,54 @@
---
title: PostCalendar介绍
typora-root-url: PostCalendar介绍
date: 2022-03-05 14:18:50
tags:
---
# PostCalendar介绍
> 本文是[PostCalendarWindows](https://https://github.com/jackfiled/PostCalendarWindows)README文件的国内镜像
一款集日程管理与DDL管理于一身的日历软件。
下载地址:[GithubRelease](https://github.com/jackfiled/PostCalendarWindows/releases)
# 开发未完成,仍在内测阶段
<!--more-->
## 支持的功能
### 日历部分
![日历部分截图](Calendar.png)
1. 支持日历事件的添加,删除,修改。
2. 支持读取教务处自动生成的excel课表文件。
> 这个功能需要电脑上安装excel应用程序.
>
> 目前这个功能仅作实验性的支持不保证excel读取的完全准确。
>
> > 使用帮助在教务处网站“学期理论课表”页面有打印按钮可以下载一个excel表格。
> >
> > 下载完成后在软件里点击“导入excel课表”按钮选择excel文件下载的位置即可自动导入。
### DDL部分
![DDL部分截图](DDL.png)
1. 支持DDL事件的添加修改完成删除。
2. 可以将活动界面中DDL类型的事件直接添加到个人DDL中。
### 活动部分
![活动部分截图](Activity.png)
**本部分未完成,设想中将与[DDL网站](http://squidward.top)的数据进行同步**
## 使用方法
软件依赖于.net6.0,请点击[链接](https://dotnet.microsoft.com/zh-cn/download/dotnet/thank-you/runtime-desktop-6.0.2-windows-x64-installer)下载.net6.0运行时。
在安装完成或者确认电脑上已安装.net6.0运行时之后点击下载旁边的release包双击下载文件中的PostCalendarWindows.exe即可使用。

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -0,0 +1,20 @@
---
title: 程序设计与计算导论笔记
date: 2021-11-17 16:38:30
tags:
- 学习资料
---
# 程序设计与计算导论笔记
直接扒的老黄的PPT ,简直毫无参考价值。
不保证笔记的绝对正确性。
如果导致考试爆炸,不承担任何责任。
<!--more-->
## 第一章——程序设计概论
![第一章](./program-design-introduction/1.png)
## 第二章——C语言概述
![第二章](./program-design-introduction/2.png)
![第二章](./program-design-introduction/3.png)

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -0,0 +1,87 @@
---
title: 初学Qt的一点小笔记
tags:
- 技术笔记
- C/C++
typora-root-url: qt-learning
date: 2022-07-01 14:32:39
---
# 初学Qt的一点小笔记
最近的大作业需要用 `C/C++`的技术栈实现一个图形化界面,`Qt`作为C++图形化框架久负盛名,正好借着这个写大作业的机会学习一下这个应用广泛的框架。
<!--more-->
## Qt的安装
现在比较新版本的Qt貌似都不支持下载离线安装包了受制于网络环境在线安装的体验并不是很好。为了比较顺利的完成安装使用老套路——国内镜像。清华大学就提供了Qt在线安装的镜像具体的使用说明参照镜像的这篇[帮助](https://mirrors.tuna.tsinghua.edu.cn/help/qt/)在下载之前记得注册一个Qt的账号。
### 版本的选择
现在`Qt`最新的版本已经来到了`Qt6`,虽然现在`Qt5`仍然十分的流行,网上大部分的资料与教程都是采用`Qt5`写成的,我最后还是选选择了`Qt6`,理由主要有以下三点:
- 工程并不是很复杂,而且开发的周期很长,即使在中间遇到了一些新版本的玄学问题,我也有比较充足的时间来解决或者避开问题
- `Qt6`开始完全转向`cmake`管理项目,而我的这个大作业“恰好”就是采用`cmake`管理的
- `Qt6`是新版本,以后开发的时间还很长,稳定的开发环境还不是我现在需要的,学习的人还是应该积极的跟踪新技术(当然只是我自己的想法)
### 编译器的选择
我在`Windows`平台上进行开发,虽然在之前学习过程中`MinGW64 GCC`是我更常用的编译器,但是他毕竟是一个移植的编译器,而不是“官方”的编译器,我选择了`MSVC`作为这次项目的编译器。
>这里还有一个理由是我正在大力推进`WSL`在我日常开发中的使用,我正在把我所有的`C/C++`项目都迁移到`WSL`中进行开发,在`Windows`中我已经不保留`MinGW64`编译器了。
### 预处理的使用
在这次`Qt`开发中我用到了两个预处理器——`moc``uic`,前者服务于`Qt`的元对象系统(Meta Object System),后者负责与将`Qt Designer`生成了`*.ui`文件转换为编译器可以编译的`ui_*.h`文件。这里重点说说前者,`Qt`的元对象系统是`Qt`信号和槽机制的基础,所有需要用到信号槽的类都需要继承`QObject`这个基类,同时在类里申明`Q_OBJECT`这个宏,而且,这个头文件还得被`moc`预处理器预处理为`moc_*.cpp`之后才能被编译器所编译,否则就会报`LNK2001`连接错误,提示有三个函数无法找到定义,
```
@errorMsg.obj : error LNK2001: unresolved external symbol "public: virtual struct QMetaObject const * __thiscall errorMsg::metaObject(void)const " (?metaObject@errorMsg@@UBEPBUQMetaObject@@XZ)
errorMsg.obj : error LNK2001: unresolved external symbol "public: virtual void * __thiscall errorMsg::qt_metacast(char const *)" (?qt_metacast@errorMsg@@UAEPAXPBD@Z)
errorMsg.obj : error LNK2001: unresolved external symbol "public: virtual int __thiscall errorMsg::qt_metacall(enum QMetaObject::Call,int,void * *)" (?qt_metacall@errorMsg@@UAEHW4Call@QMetaObject@@HPAPAX@Z)@
```
在我这次的工程中,需要以下设置才能让`moc`预处理器正确工作:
-`CMakeLists.txt`文件中需要定义`set(CMAKE_AUTOMOC ON)`
- 在包含这个头文件的地方需要将头文件的名称改为预处理之后的名称`moc_*.cpp`,如下图所示
![](1.png)
## Qt Designer
在一开始我对于这个软件的使用是比较迷茫的,没有搞明白哪些内容是在`Designer`中完成的,哪些内容是在代码中完成的,在代码中是如何访问控件的。
> 这里需要说明的是,我是用`CLion`作为IDE开发`C/C++`项目,在这里`Qt Designer`是作为外部工具存在的。
```C++
MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent)
{
ui = new Ui::MainWindow;
ui->setupUi(this);
}
```
那个名叫`Ui`的命名空间让我迷茫了一阵子在那个空间中也有一个和当前创建的UI类名字相同的类我以为这是单例模式之类的高级设计模式在研读了几篇博客查看了`UIC`处理器生成的头文件之后,我才意识到这是两个处在不同命名空间但名字相同的类,在`Ui`命名空间中的那个类就是`*.ui`文件中定义了那个界面,可以通过这个指针来访问我们在`Qt Designer`中定义的那些控件。
## Qt Property Animation
`QPropertyAnimation`是`Qt`自己实现的一个简单实用的动画框架,在这次开发中,我使用这个框架实现了对`QGraphicsItem`这个对象的动画。这里主要的问题是,`QGraphicsItem`这个类并没有继承`QObject`,然而`QPropertyAnimation`这个动画框架所作用的对象必须是一个继承自`QObject`的对象,而且需要实现动画的属性必须注册`Q_PROPERTY`,根据文档的说明,我定义了这样的一个类:
```C++
class BusItem: public QObject, public QGraphicsPixmapItem
{
Q_OBJECT
Q_PROPERTY(QPointF pos READ pos WRITE setPos)
public:
explicit BusItem(const QPixmap& pixmap);
};
```
这个类多重继承了`QObject`和`QGraphicsPixmapItem`,这样既可以被`QPropertyAnimation`所作用,也可以像正常的`QGraphicsItem`一样被添加进`QGrphicsScene`并设置各种属性。
而`Q_PROPERTY`这个宏给`Qt`的类型系统注册了一个类型为`QPointF`名叫`pos`的变量,这个变量的读通过调用`pos()`函数来实现,这个变量的写通过调用`setPos()`函数来实现,这个变量也就是我需要设计动画的变量。
> 这句代码给我的感觉像是在C#中的`set`和`get`两个访问器。

BIN
YaeBlog/source/qt-learning/1.png LFS Normal file

Binary file not shown.

View File

@@ -0,0 +1,64 @@
---
title: 安装vs2019踩的坑
date: 2021-08-14 10:06:00
tags:
- 技术笔记
---
# 安装Visual Studio 2019中遇到的坑
在某个月黑风高的夜晚我在折腾了很久的Python之后突然感觉自己应该去学学C和C++于是乎我便打算折腾一下在vscode上写C和C++。在网上一番搜寻之后,我发现了这篇[知乎文章](https://zhuanlan.zhihu.com/p/87864677)和这篇[知乎文章](https://zhuanlan.zhihu.com/p/147366852),然后我就被安装MinGW编译器和配置一大堆的json文件给干碎了。<br>
于是我决定转向传说中的宇宙第一IDE——Visual Studio。<br>
<!--more-->
上网一查现在最新的vs版本是2019于是立刻进入[Visual Studio官网](https://visualstudio.microsoft.com/zh-hans/vs/)点击下载vs2019<del>enterprise</del>Community版。<br>
> 无他,就是太穷了。<br>
在点击下载链接之后,跳转到了感谢下载的界面。<br>
![](./question-in-install-vs-2019/1.png)
上面清楚的写着,下载将很快开始。
在经过漫长的等待之后,我下载下来了这个东西
>vs_community__355502915.1625217430.exe
于是一波双击飞快地下载安装选好工作负载又在一波漫长的下载之后我兴奋的双击打开了安装好的“vs2019”。
但是我却惊讶的发现我安装的是Visual Studio 2017!
我当时就是一脸懵逼想了想以为是自己在安装工作负载的时候选择错了vs的版本于是我又打开了visual studio installer却惊讶的发现只能安装vs2017的社区版专业版和企业版。
>不可能,微软的软件不会出错,一定是我自己选错了。
我立刻卸载了电脑上的vs2017和Visual Studio Installer,再次前往vs的[官网](https://visualstudio.microsoft.com/zh-hans/vs/),这次我前检查后检查确定自己下载的是Visual Studio 2019的Community版本在单击了下载链接之后我又跳转到了感谢下载的界面。
![](./question-in-install-vs-2019/1.png)
但是这次,在令人十分无语的等待之后,<strong>我不得不点了下单击此处以重试</strong>。
在一段令人紧张的等待之后Visual Studio Installer安装好了我也失望的发现我安装的仍然是vs2017。
>谢谢,电脑已经砸了。
但是,作为一个程序员,我们不能说不!
于是,我想到,既然下载开始的如此之慢,要不,<b>挂个梯子</b>试试?
说做就做我又卸载了Visual Studio Installer,在打开VPN之后我又双打开了[Visual Studio官网](https://visualstudio.microsoft.com/zh-hans/vs/), 怀着紧张而激动的心情点击了vs2019社区版的下载按钮。仍然一如既往的跳转到了感谢下载的界面不过这次下载几乎立刻就开始了
>OHHHHHHHHHHHHHHHHHHH
接着就是双击下载安装我打开Visual Studio Installer让我安装的果然是vs2019接着我泪流满面的选好了工作负载点击了下载。
## 现在,我们来复盘一下
我记不清清楚我第一次下载时是否点击了<i>单击此处以重试</i>,但是我的第二次尝试时确定点击了的在结合开了VPN立刻下载的”解法“我便将注意力放在了这个按钮上。
这是点击重试之后的下载地址:
```
https://download.visualstudio.microsoft.com/download/pr/343898a7-7d12-4faa-b5df-958b31e57b3e/0e17eb53023c8a4d07e1dfd201e8a0ebff2c56c74ad594c8f02521fb5b27c7db/vs_Community.exe
```
这是不点击重试的下载地址:
```
https://download.visualstudio.microsoft.com/download/pr/45dfa82b-c1f8-4c27-a5a0-1fa7a864ae21/9dd77a8d1121fd4382494e40840faeba0d7339a594a1603f0573d0013b0f0fa5/vs_Community.exe
```
下面是我挂着梯子下载下来的安装程序的MD5值
>7382158e92bb9af82a24c5c3eba80c20
下面是不单击重试下载的安装程序的MD5值
>7382158e92bb9af82a24c5c3eba80c20
下面是单击重试下载的安装程序的MD5值
>88f28257ae1e6ce4a7ebd5d6f7f94f0f
至此,真相已经摆在了我的面前。
## 总结
在感谢下载的页面如果你耐心等待那么在一段时间后下载的就是vs2019但是如果你是一个急性子点击了“单击此处以重试”的按钮。那么你下载的就是vs2017的版本。

Binary file not shown.

View File

@@ -0,0 +1,235 @@
---
title: 软件工程
tags:
- 软件工程
- 笔记
date: 2024-06-12 20:27:25
---
你说得对但软工无非就是瀑布模型规定的那六项基本活动及其变化然后细化到需求分析需要用UML规范化表示的建模方法后面就是如何通过框架模块的结构确定软件对象有哪些并分配功能。当然这其中也涉及到模块独立性的设计原则以及面向对象的7个设计原则之后就是软件测试的白盒和黑盒方法。
## 软件工程概述
软件是包括程序、数据及其相关文档的完整集合。IEEE的定义是软件是计算机程序、规程以及运行计算机系统所需要的文档和数据。
在20世纪的60年代随着计算机软件引用领域增多软件规模不断扩大软件系统功能多样、逻辑复杂不断扩充从而导出系统开发出现不良的后果
- 软件开发计划难以制定和实施
- 软件开发费用和进度失控
- 软件的质量无法让用户满意
- 软件无法维护
- 软件没有适当的文档资料
这就是**软件危机**。解决软件危机的方法就是软件工程。
F.L. Bauer提出软件工程就是为了经济地获得能够在实际机器上搞笑运行的可靠软件而简历和使用的一系列高的工程化原则。Barry Boehm提出软件工程是运行现代科学技术知识来设计并构造计算机程序及为开发、运行和维护这些程序所必需的相关文件资料。Richard E. Fairley则认为软件工程学是为了在成本限额之内按时完成开发和修改软件产品所需的系统生产和维护的技术和管理的学科。IEEE计算机学会将软件工程定义为应用系统化的、规范化的、定量的方法来开发、运行和维护软件以及对于这其中各种方法的研究。
软件工程中的三要素为:
- 方法:给出需求、设计建模、编码和测试的方法
- 工具:给出各种自动或者半自动的软件支撑环境
- 过程:将软件工程的方法和工具综合起来以达到合理、及时地进行计算机软件开发的目的,给出指导软件开发所需要的过程模型。
软件工程的目标是:
- 现实目标:在一个特定的项目中,在给定成本和时间的前提下,开发出满足用户需求且具有正确性、可用性等因素的软件产品。
- 终极目标:摆脱手动生产软件的状况,逐步实现软件研制和维护的自动化。
软件工程的原则是:
- 选择合适的开发模型
- 采用合适的设计方法
- 提供高质量的工程支持力度
- 重视开发过程的管理
## 软件生命周期模型
软件工程过程是为了获得软件产品在软件工具的支持下由软件工程师完成的一系列软件工程活动。主要活动有1编写软件规格说明2软件开发3软件确认4软件演进。
软件生命周期是指软件产品从考虑其概念开发,直到废弃为止的整个时期,总的包括概念阶段,分析与设计阶段,构造阶段,移交和运行阶段等不同的时期。总共存在六个步骤:
1. 制定计划。
2. 需求分析
3. 软件设计
4. 程序编码
5. 软件测试
6. 运行维护
软件生命周期模型是一个框架,描述从软件需求定义直到软件经使用后废弃为止,跨越整个生存期的软件开发,运行和维护所实施的全部过程、活动和任务,同时描述生命周期不同阶段产生的软件工件明确活动的执行角色。
### 传统生命周期模型
#### 瀑布模型
![image-20240620211321957](software-engineer/image-20240620211321957.png)
瀑布模型强调在软件实现之前必须进行分析和设计工作,同时也造成了模型缺乏灵活性的问题,特别是面对软件的需求不明确或者不准确的情况时,模型的风险控制能力较弱。
因此瀑布模型中存在一个“do twice"的概念,即在交付给使用者之前的软件开发要做两次。
#### 演化模型
烟火模型提倡进行两次开发。第一次开发得到实验性的原型产品,其目的是探索可行性,弄清软件的需求。第二次在第一次的基础上获得较为满意的软件产品。
![image-20240620212101864](software-engineer/image-20240620212101864.png)
演化模型在明确用户需求和降低开发风险的同时,也带来了难以管理、结构较差和技术不成熟的问题,同时可能抛弃掉瀑布模型的文档控制优点。因此演化模型更多适合于需求不清晰的小型或中型系统,适用于开发周期较短的场合。
#### 增量模型
![image-20240620214307906](software-engineer/image-20240620214307906.png)
但是在增量模型中难以确定增量的粒度,同时确定所有的需求比较困难。
#### 喷泉模型
![image-20240620214739548](software-engineer/image-20240620214739548.png)
各个开发阶段没有特定的次序,可以并行进行,也可以在某个开发阶段中随时补充其他任何开发阶段。但是难以管理,工作计划需要随时更新。
#### V模型和W模型
将测试活动提前,使得瀑布模型能够驾驭风险。
![image-20240620215022645](software-engineer/image-20240620215022645.png)
#### 螺旋模型
![image-20240620220155962](software-engineer/image-20240620220155962.png)
四个象限:制定计划、风险分析、实施工程、客户评价。
#### 构件组装模型
利用模块化思想将整个系统模块化,并在一定构件模型的支持下复用构件库中软件构件,通过组装高效率、高质量地构造软件系统。构件组装模型本质上是演化模型。
![image-20240620224318982](software-engineer/image-20240620224318982.png)
充分利用软件复用,提高开发效率。允许多个项目同时开发,降低了费用,提高了可维护性。但是缺乏通用的构件组装结构标准,风险较大,同时构件可重用性和系统高效性之间不易协调。
#### 快速应用开发模型
![image-20240620224519243](software-engineer/image-20240620224519243.png)
增量型的软件开发过程,强调极短的开发周期。
#### 原型方法
考虑到完整而准确的需求规格说明是很难一次性得到的。
原型方法通过在获得一组基本需求之后,通过快速分析构造出一个小型的软件系统原型,满足用户的基本要求。
原型方法可以分为废弃策略和追加策略。废弃策略中的原型方法主要是探索和实验的目的,追加策略主要是进化型,将原型方法的思想拓展到软件开发的全过程中,适用于需求经常变动的软件项目。
原型提供了用户和开发人员良好的沟通手段,易于被人们接受。但是对于大型系统和存在大量运算、逻辑性较强的程序模型可能不太适用。同时可能会造成文档容易被忽略,同时建立原型的许多工作会被浪费掉。
### 新型软件生命周期模型
#### RUP
Rational Unified Process的生命周期在时间上被分解为四个顺序的阶段
- 初始阶段:通过业务场景了解业务并确定项目的边界。
- 细化阶段:分析问题领域,建立适合需求的软件体系结构基础,编制项目计划,完成项目中技术要求高,风险大的关键需求的开发。
- 构造阶段:所有剩余的技术构建和稳定业务需求功能开发完成,所有功能被详细测试。
- 移交阶段:确保软件对最终用户是可用的。
总的来说,以用例为驱动的,软件体系结构为核心,应用迭代及增量的新型软件生命周期模型。
RUP由9个核心工作流构建每个迭代的主要活动。分别是6个核心过程工作流业务建模、需求、分析和设计、实现、测试、部署和三个核心支持工作流配置和变更管理、项目管理和环境。
#### 敏捷建模
敏捷建模由一系列的价值观、原则和实践组成,是一种快速软件开发的思想代码,代表性的应用有极限编程。
![image-20240621114540033](software-engineer/image-20240621114540033.png)
极限编程中的需求分析要求开发人员和客户一起将各种需求变成小的需求模块User Story这些模块将会被组合或者分解为更小的模块成为Story Card。
极限编程的设计和开发强调测试驱动的开发,提倡在开发过程中常常进行设计复核、代码复核和重整和优化。
极限编程的测试通常集成在设计和开发过程中并且提倡持续集成CI在开发过程中经常进行整合并运行单元测试。
## 软件需求分析
软件开发人员通过和软件产品的使用者和拥有者交流和调研获取的相关业务职能、业务知识和业务流程等信息,并对这些信息进行分析和整理后形成的有关该软件产品必须提供的功能和性能等指标的规格描述。
软件需求分析的任务就是通过一个无二义性的方式,将软件的需求严格地、形式的表达出来,并为用户和软件开发人员所接受。
软件需求分析的目标是借助于业务系统的逻辑模型导出软件系统的逻辑模型。解决目标系统“做什么”的问题。
在软件需求建模中需要遵循三条原则:
- 问题的信息域必须被表示和理解
- 软件将完成的功能必须被定义
- 软件的行为(作为外部事件的结果)必须被表示
软件需求工作分成软件需求的获取和软件需求的管理两个部分,其中管理负责需求的确认、需求的跟踪和需求的变更控制等内容。
软件的需求可以分为功能需求和非功能需求,其中非功能需求包括性能需求、环境需求和可靠性需求等。
软件需求的两个产出:
1. 用户需求说明书:对收集到的所有需求信息进行整理和分析,消除错误,归纳与总结共性的用户需求。
2. 软件需求规格说明书:从用户需求说明书出发,对比较复杂的需求进行建模分析,细化所有的软件功能,剔除不合理的部分,增加需要的部分,最后给出系统的逻辑模型。
### 面向对象的需求分析方法
UML即统一建模语言是面向对象分析与设计的一种标准表示。
4+1视图通过模型来描述系统的结构和行为或者说静态结构和动态结构以用例视图为核心描述系统的不同视图。
![image-20240623160826903](software-engineer/image-20240623160826903.png)
#### 领域模型
领域模型是针对某一个特定领域内概念类或者对象的抽象化可视化表示。
![image-20240623162229404](software-engineer/image-20240623162229404.png)
在领域模型中使用类图表达概念及其关系,概念类之间的关系有关联、继承、组合、聚合和依赖等关系。
#### 用例模型
用途模型由用例图和解释实现用例过程的用例描述组成。用例是从使用系统的角色出发描述使用者与系统或者系统某个功能之间的交互场景,用来描述用户对于系统的功能需求。
用例模型一般由四个部分组成,分别是用例图、用例说明、系统顺序图和操作契约,其中前两者是必需的,后两者是可选的。操作契约一般包括三部分的内容:对象的创建或者消除,对象之间关联的创建和删除、对象的属性修改。
## 软件设计
软件设计的目标是根据需求分析的结果设想并设计软件,从概念模型出发得到物理模型。软件设计包括软件系统的结构设计、处理方式的设计、数据结构和数据存储的设计和界面、可靠性设计等。
软件的设计应该注意软件结构的模块化。模块具有独立性和耦合性。
模块的内聚性是模块功能强度的度量。
![image-20240623163647935](software-engineer/image-20240623163647935.png)
模块的耦合性是针对模块之间连接紧密程度的度量。
![image-20240623170058679](software-engineer/image-20240623170058679.png)
面向对象的设计原则:
- 单一职责原则
- 开闭原则
- 狄米特原则
- 开闭原则
- 依赖倒置原则
- 里氏替换原则
- 接口隔离原则
### 面向对象的设计方法

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -0,0 +1,317 @@
---
title: SpringBoot自定义注解实现权限控制
tags:
- 技术笔记
- Java
date: 2023-07-29 15:20:02
---
# SpringBoot自定义注解实现权限控制
<!--more-->
## 需求分析
最近在用`SpringBoot`写一个数据结构的大作业,实现一个日程管理系统。在系统需要有不同用户的权限管理功能。但是`SpringBoot`框架中使用的`Spring Security`权限控制框架有点过于“重”了,对于我们这种小项目来说不太适用。
于是我们打算利用`Spring`中比较强大的注解功能自行设计实现一套权限控制功能。这个功能需要实现一下这些功能:
- 基于`Json Web Token`的登录状态维持。
- 不同的用户具有不同的权限
- 使用注解注明每个接口设置的权限类型
- 在控制器中可以获得当前请求用户的身份信息
## 具体实现
### 权限等级和策略等级
首先明确一下我们需要支持的权限等级,通过枚举的方式表现:
```java
public enum UserPermission {
USER(0, "user"),
ADMIN(1, "administrator"),
SUPER(2, "superman");
private final int code;
private final String name;
UserPermission(int code, String name) {
this.code = code;
this.name = name;
}
public int getCode() {
return code;
}
public String getName() {
return name;
}
}
```
这里我们使用了经典的三层等级制度。
然后明确一下我们对于各个接口的权限要求,这里也采用枚举的方式给出:
```java
public enum AuthorizePolicy {
/**
* 只要登录就可以访问
*/
ONLY_LOGIN("onlyLogin"),
/**
* 用户在当前请求的组织中
*/
CURRENT_GROUP_USER("currentGroupUser"),
/**
* 用户在当前请求的组织中 且权限在管理员之上
*/
CURRENT_GROUP_ADMINISTRATOR("currentGroupAdministrator"),
/**
* 用户在当前请求的组织中 且权限在超级管理员之上
*/
CURRENT_GROUP_SUPERMAN("currentGroupSuperman"),
/**
* 当前用户可以访问URL终结点包含用户ID
*/
CURRENT_USER("currentUser"),
/**
* 用户权限超过普通管理员
*/
ABOVE_ADMINISTRATOR("aboveAdministrator"),
/**
* 用户权限超过超级管理员
*/
ABOVE_SUPERMAN("aboveSuperman");
private final String implementName;
AuthorizePolicy(String implementName) {
this.implementName = implementName;
}
public String getImplementName() {
return this.implementName;
}
}
```
这里`current`开头相关策略有点粪的一点是,为了确保每个用户只能访问自己相关的数据,我们会从请求`url`中读取当前请求对象的ID。因为我们采用了`RESTful API`的设计思想,因此形如`/user/1`之类的请求就表示对于ID等于1的用户进行请求。但是这样设计就存在两个问题
- 从编程的角度出发,`current`相关策略就只能使用在`url`最后为对象ID的接口上但是这是一个**口头约定**,实际代码中没有任何限制,因此当错误使用这类策略时就会引起不必要的运行时错误。
- 从应用的角度出发,从`url`中获得数据也显得有一点奇怪。
### 策略实现服务
为了实现不同策略服务,我们设计了一个认证接口:
```java
package top.rrricardo.postcalendarbackend.services;
import top.rrricardo.postcalendarbackend.dtos.UserDTO;
import top.rrricardo.postcalendarbackend.exceptions.NoIdInPathException;
public interface AuthorizeService {
/**
* 验证用户的权限
* @param user 用户DTO模型
* @param requestUri 请求的URI
* @return 是否通过拥有权限
*/
boolean authorize(UserDTO user, String requestUri) throws NoIdInPathException;
}
```
其中输入的两个参数分别是在令牌中解析出来的用户信息(通过`json`的形式存储在`JWT`令牌中)和当前请求的`url`
然后针对每个策略实现一个认证服务:
![image-20230727175807814](spring-boot-custom-authorize/image-20230727175807814.png)
> 具体实现就不在这里给出。
在注入每个服务时,使用策略枚举作为服务的名称,方便后续获得该服务实例。
![image-20230727175955817](spring-boot-custom-authorize/image-20230727175955817.png)
### 注解和注解解析
首先实现一个**运行时****注解在方法上**的注解:
```java
import java.lang.annotation.*;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@Documented
@Inherited
public @interface Authorize {
AuthorizePolicy policy() default AuthorizePolicy.ONLY_LOGIN;
}
```
然后实现一个注解处理器:
```java
package top.rrricardo.postcalendarbackend.components;
import io.jsonwebtoken.JwtException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import top.rrricardo.postcalendarbackend.annotations.Authorize;
import top.rrricardo.postcalendarbackend.dtos.ResponseDTO;
import top.rrricardo.postcalendarbackend.dtos.UserDTO;
import top.rrricardo.postcalendarbackend.exceptions.NoIdInPathException;
import top.rrricardo.postcalendarbackend.services.JwtService;
@Component
public class AuthorizeInterceptor implements HandlerInterceptor {
private final JwtService jwtService;
private final AuthorizeServiceFactory authorizeServiceFactory;
private static final ThreadLocal<UserDTO> local = new ThreadLocal<>();
public AuthorizeInterceptor(JwtService jwtService, AuthorizeServiceFactory authorizeServiceFactory) {
this.jwtService = jwtService;
this.authorizeServiceFactory = authorizeServiceFactory;
}
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
if (!(handler instanceof HandlerMethod handlerMethod)) {
return true;
}
var method = handlerMethod.getMethod();
var authorize = method.getAnnotation(Authorize.class);
if (authorize == null) {
// 没有使用注解
// 说明不需要身份验证
return true;
}
// 验证是否携带令牌
var tokenHeader = request.getHeader(jwtService.header);
if (tokenHeader == null || !tokenHeader.startsWith(jwtService.tokenPrefix)) {
var responseDTO = new ResponseDTO<UserDTO>("No token provided.");
response.setStatus(401);
response.getWriter().println(responseDTO);
return false;
}
try {
var claims = jwtService.parseJwtToken(tokenHeader);
var userDTO = new UserDTO(
claims.get("userId", Integer.class),
claims.getIssuer(),
claims.get("emailAddress", String.class)
);
var authService = authorizeServiceFactory.getAuthorizeService(authorize.policy());
if (authService.authorize(userDTO, request.getRequestURI())) {
local.set(userDTO);
return true;
} else {
var responseDTO = new ResponseDTO<UserDTO>("No permission");
response.setStatus(403);
response.getWriter().println(responseDTO);
return false;
}
} catch (JwtException e) {
// 解析令牌失败
var responseDTO = new ResponseDTO<UserDTO>(e.getMessage());
response.setStatus(401);
response.getWriter().println(responseDTO);
return false;
} catch (NoIdInPathException e) {
// 在请求路径中没有获取到用户ID
var responseDTO = new ResponseDTO<UserDTO>("Internal server error, please contact administrator");
response.setStatus(500);
response.getWriter().println(responseDTO);
return false;
}
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
local.remove();
}
public static UserDTO getUserDTO() {
return local.get();
}
}
```
其中重要的部分是声明了一个`ThreadLocal`的变量,当前的处理线程可以通过这个变量获得当前发起请求的用户信息。
在上述实现中还涉及到使用`AuthorizeServiceFactory`的部分,这是因为在配置注解处理器时不能使用依赖注入,需要手动创建对象:
```java
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import top.rrricardo.postcalendarbackend.components.AuthorizeInterceptor;
import top.rrricardo.postcalendarbackend.components.AuthorizeServiceFactory;
import top.rrricardo.postcalendarbackend.services.JwtService;
@Configuration
public class WebMvcConfiguration implements WebMvcConfigurer {
private final JwtService jwtService;
private final AuthorizeServiceFactory authorizeServiceFactory;
public WebMvcConfiguration(JwtService jwtService, AuthorizeServiceFactory authorizeServiceFactory) {
this.jwtService = jwtService;
this.authorizeServiceFactory = authorizeServiceFactory;
}
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new AuthorizeInterceptor(jwtService, authorizeServiceFactory));
}
}
```
我们就实现了一个`AuthorizeServiceFactory`,在解决依赖注入问题的同时封装了一部分的逻辑:
```java
import org.springframework.stereotype.Component;
import top.rrricardo.postcalendarbackend.enums.AuthorizePolicy;
import top.rrricardo.postcalendarbackend.services.AuthorizeService;
import java.util.Map;
@Component
public class AuthorizeServiceFactory {
Map<String, AuthorizeService> authorizeServiceMap;
public AuthorizeServiceFactory(Map<String, AuthorizeService> authorizeServiceMap) {
this.authorizeServiceMap = authorizeServiceMap;
}
public AuthorizeService getAuthorizeService(AuthorizePolicy policy) {
return authorizeServiceMap.get(policy.getImplementName());
}
}
```
## 实际引用
我们在项目[PostCalendarBackend](https://github.com/post-guard/PostCalendarBackend)中实际使用的这个技术相关代码在可以在Github上获取。

View File

@@ -0,0 +1,78 @@
---
title: 被Windows更新狂暴鸿儒的Arch Linux
tags:
- 技术笔记
- Linux
date: 2023-11-05 14:34:36
---
在Windows更新之后发现Linux无法启动之后面露难色的~~两人~~一人。
<!--more-->
## 故障现象
某日Windows进行了一次更新本以为无事发生结果第二天试图启动Linux时发现
```
Initramfs unpacking failed: invalid magic at start of compressed archive
```
## 修复
首先判断是Windows更新橄榄了Linux启动使用的`initramfs`导致的,关于这个东西的介绍详解[Arch boot process](https://wiki.archlinux.org/title/Arch_boot_process#initramfs)。
于是尝试使用`Arch ISO`启动系统重新生成`initramfs`解决。
`arch-chroot`之后使用`mkinitramfs -P`试图重新生成`initramfs`,但是在重启之后仍然出现类似的提示。遂求助伟大的搜索引擎。
发现搜索引擎给出了相同的解决方案,,,这时我已经开始慌乱了。再次进入`Arch ISO`打包`home`目录为重装做准备。
有帖子分析说Windows更新可以会把`/boot`的分区格式给橄榄,可以尝试使用`fsck`进行修复。
进入`Arch ISO`,使用
```shell
fsck -r /dev/nvmen0p1
```
对分区进行修复,没想到还扫描出现错误:
```
There are differences between boot sector and its backup.
This is mostly harmless.
```
具体提示的错误bit我给忘记了
我选择使用`Copy backup to original`来修复这个错误。还出现了一个
```
two or more files share the same cluseters
```
的错误,冲突的文件是`amd-ucode.img``bootmgfw.efi.mui`文件,我也选择了修复。
我又在网上翻到一篇帖子说可以试试`pacman`更新系统和重新安装`linux`包,再想到这两天一直在`Windows`下写文档,确实可以试试,于是就:
```shell
pacman -Syu
pacman -Sy linux
```
回来吧我的Linux
## 总结分析
因为在第二次进入`Arch ISO`中我同时使用了`fsck``pacman`两个工具同时进行修复,因此我无法判断具体是哪个工具修复了这个问题,不过鉴于这次更新也没有安装新的内核版本,而且我之间也已经手动执行过`mkinitramfs -P`
在加上在互联网上已经有大量关于Windows更新可能会破坏启动分区尤其是这次的Windows更新还是一个较大的版本更新因此我认为就是Windows干的好事微软你不得house
## Update at 2023-11-12
今天早上爬起来一看Linux又启动失败了。
这波我实在是蚌埠住了直接把Windows干掉算了
得到的教训就是如果要装双系统最好在两块不同的硬盘上安装系统这样Windows就没有办法对于Linux那边的`boot`分区上下其手了。

Some files were not shown because too many files have changed in this diff Show More