你好,2021

四级更迭,时光流转,又一个按下了快进键的365天。告别2020年,感谢遇见你2021,还请多多指教。

过去的2020年,经历了新冠病毒的侵袭,经历了全民隔离,网课教学。2020年的上半年是黑白的,感觉时间都被暂停了。但多亏大家的努力,让2020年的下半年逐渐重返前进的轨道之上,希望2021年,能够牛转乾坤,为美好的生活继续努力。

2020年,我第一次参加了微信小程序全国高校大赛,取得了华南赛区三等奖。但这个奖不会是我的终点,它会继续激励我,向着更高的目标继续进发,希望能够在未来取得更好的成绩。从年初的0.0.1版的GCU课表+,一直迭代到今天的1.8.1版本,一年来我对这个小程序进行了上百次的更新,现在回头看真的是成就感满满,即学习到了开发方面的知识,交到了更多的好友,也帮自己争得了一个奖项,希望明年能够继续进步。

2021年,一个新的开始,一页新的篇章,下面是我短期(1-2月)的一个目标。

  1. GCU课表+ 功能增强
  2. 自制LL(1)文法的编译器
  3. 学会用Coco2dx制作小游戏
  4. 用库乐队做一个 trap beat
  5. 雅思考到6.5

希望一切都能如约而至,也祝福大家心想事成,学业进步,身体健康。

[NodeJS]非抢占式多级反馈队列调度算法

前序

《操作系统》课程最近布置了一个大作业,要求我们每人实现一个非抢占式多级反馈队列调度算法的模拟程序,作为期末考核的一部分。(u1s1,真的是爽到,老师开心,我们也写的开心!)

实现代码

//Powered By 7gugu

//每一级队列的可运行时间
let timeSlice = [1, 2, 3];

//准备运行的队列
let preRunQueue = [];
//3级运行队列
let runQueue = [
  [],
  [],
  []
];

//准备运行的程序[开始时间, 运行时间]
let progs = [
  [0, 8],
  [1, 4],
  [5, 1],
  [3, 7],
  [4, 2]
];

for (let i = 0; i < progs.length; i++) {
  let prog = {};
  prog.id = "P" + i;
  prog.startTime = progs[i][0];
  prog.runTime = progs[i][1];
  prog.priority = 0; //设置最高优先级
  preRunQueue.push(prog); //把待运行的程序导入运行序列
}

//总运行时间
let totalTime = 0;

while (true) {
  //如果待运行队列中仍然有程序 & 程序已到达开始时间
  if (preRunQueue.length > 0) {
    let prog = preRunQueue[0];
    if (prog.startTime <= totalTime) {
      preRunQueue.shift(); //直接弹出队头的元素
      runQueue[0].push(prog); //把程序加入0级运行队列中
      console.log(prog.id + "开始运行,开始时间为:" + totalTime);
    }
  }

  for (let i = 0; i < runQueue.length; i++) {
    //如果各级队列还有程序的话,就继续运行
    if (runQueue[i].length > 0) {
      let prog = runQueue[i].shift(); //获取各级队列中第一个程序
      if (prog.runTime > timeSlice[i]) {
        //程序运行时间比时间片大
        totalTime = totalTime + timeSlice[i]; //总运行时间累加
        prog.runTime = prog.runTime - timeSlice[i]; //减去每一次运行的时间
        if (i != runQueue.length - 1) {
          //如果未处于最低优先级,则把程序放在下一个优先级队列中
          runQueue[i + 1].push(prog);
        } else {
          //如果处于最低优先级,则把程序放回最低优先级中运行
          runQueue[i].push(prog);
        }
      } else {
        //程序运行时间比时间片小
        totalTime = totalTime + prog.runTime;
        console.log(prog.id + "运行完成,目前时间为:" + totalTime);
      }
      break;
    }
  }
} 

运行结果

仓库地址

参考资料

计算机操作系统(第四版) 西安电子科技出版社

[小程序]PPG式心率测量模块

最近有空把之前想做的心率测量进行了开发和研究,最终选择了运动手环上面普遍采用的PPG式心率测量,载体则继续使用之前开发的”活力健身房”小程序。

什么是PPG式心率测量?

PPG是通过光电手段在活体组织中检测血液容积变化的一种无创检测方法。

测量的原理是啥?

计算一段时间内的波峰数量以及间隔时间即可计算心率

原理:血液会吸收光纤,心跳时血液流量会规律性变化,进而产生规律性变化,进而产生规律性的光信号。

Demo视频

小程序码

活力健身房

使用方法

  1. 扫描小程序码
  2. 点击”我”
  3. 点击进入”心率测量”模块
  4. 阅读使用注意事项,点击下一步
  5. 开始测量,当剩余时间倒数至零时,即会生成测试结果

引用

  1. https://www.richtek.com/Design%20Support/Technical%20Document/AN057?sc_lang=zh-CN
  2. https://blog.csdn.net/QQ576494799/article/details/105024692/

ES6中的箭头函数()=>与function的区别

  1. 写法不同
  2. this指向不同
  3. 构造函数
  4. 变量提升

1.写法不同

//function
function x(a, b){
  return a + b;
}
//箭头函数
const x = (a, b)=>{
  return a + b;
}

2.this指向不同

使用function定义的函数,this的指向随着调用环境的变化而变化的,而箭头函数中的this指向是固定不变的,一直指向的是定义函数的环境。

function x(a, b){
  console.log(this);
}
const obj = ()=>{
  test: 7gugu,
}
x(); //Window
obj.test(); //obj { test: 7gugu }

使用function定义的函数中this指向是随着调用环境的变化而变化的

//使用箭头函数定义函数 
var foo = () => { console.log(this) };
var obj = { aa:foo };
foo(); //Window
obj.aa(); //Window

明显使用箭头函数的时候,this的指向是没有发生变化的。

3.构造函数

//使用function方法定义构造函数 
function Person(name, age){     
  this.name = name;   
  this.age = age; 
} 
var lenhart =  new Person(lenhart, 25);
console.log(lenhart); //{name: 'lenhart', age: 25}
//尝试使用箭头函数 
var Person = (name, age) =>{     
  this.name = name;   
  this.age = age; 
}; 
var lenhart = new Person('lenhart', 25); //Uncaught TypeError: Person is not a constructor

function是可以定义构造函数的,而箭头函数是不行的。

4.变量提升

由于js的内存机制,function的级别最高,而用箭头函数定义函数的时候,需要var(let const定义的时候更不必说)关键词,而var所定义的变量不能得到变量提升,故箭头函数一定要定义于调用之前!

foo(); //123
function foo(){     
  console.log('123');
}  
arrowFn(); //Uncaught TypeError: arrowFn is not a function 
var arrowFn = () => {     
  console.log('456'); 
};

转载自:https://blog.csdn.net/github_38851471/article/details/79446722

Vue Production环境中Proxy无效的解决思路&方法

问题

最近上线Vue项目到服务器,上传之后就出现了,代理404的问题。Dev环境中的代理是工作正常的,这点让我很疑惑,但这恰巧是我的一个误解,下面是这次的解决思路。

解决思路

一开始,我以为vue.config.js中的,devServer中的proxy是在路由(Router)层面做的数据转发,所以在这上面花了一些时间进行研究。后续通过查阅官方文档发现,devServer配置的是一个nodejs的测试服务器参数,而不是路由参数后,恍然大悟。(这就是我的误解所在)

解决这个proxy的方向,应该是关注于配置自身的HTTP服务器的代理上面,如果是Nginx,就要配置Nginx的路由转发;我这里用的是Apache作为我的HTTP服务器,所以应该配置的是对应的代理参数。

配置步骤

HTTP服务器部分

1.打开Apache的httpd.conf,开启以下两个proxy拓展,保存

LoadModule proxy_module modules/mod_proxy.so
LoadModule proxy_http_module modules/mod_proxy_http.so 

2.在https.conf中配置监听接口,保存

3.打开httpd-vhost.conf如下图配置即可

4.此时HTTP服务器部分就配置完成了,此时仅需重启Apache服务器即可生效。

Vue部分

因为是使用了History模式的路由,所以为了正确路由到相关的页面,还需要配置相关的PathRewrite才能正确路由。

1.在vue生成生产环境文件的文件夹中,添加.htaccess文件(我使用的是默认参数,所以就在dist文件夹中)

2.配置以下参数即可。(参数参考官方文档进行配置)

3.至此Vue部分配置完成,重新访问404的问题就消除了。

参考文献

  1. vue项目使用history模式打包应该注意的地方
  2. 前端用vue 上传项目,apache服务器 成功中转接口代理
  3. Apache的ProxyPass简单使用
  4. vue项目上线apache反向代理配置跨域
  5. apache proxy作用——ProxyRequests

Vue import不识别 Unexpected Token (xx:xx)

Bug出现

最近在给工作室打工的时候,Vue做了个静态路由懒加载。

然后编译的时候死活不认这个import,截图如下,完全没有解决的思路。

解决思路

  1. 同事编译莫得问题,遂排除是代码问题
  2. 清除node_module,重新npm install,无效,排除是Node的问题
  3. 因为其他位置的import工作正常,遂排除babel未启用
  4. 最后通过下载安装”syntac-dynamic-import”,在配置后,问题解决

[回溯法] 迷宫问题

问题

思路

流程图

代码

#include "pch.h"
#include 
struct Point{
	int x;
	int y;
};

int main()
{
	int max_x = 0, max_y = 0;
	int maze_arr[100][100] = { 0 };
	scanf("%d %d", &max_x, &max_y);

	if (max_x * max_y <= 0) {
		printf("Wrong input!\n");
		return 0;
	}

	if (max_x * max_y == 1) {
		printf("No solution!\n");
		return 0;
	}

	for (int i = 0; i < max_x; i++) {
		for (int j = 0; j < max_y; j++) {
			scanf("%d", &maze_arr[i][j]);
		}
	}
	
	printf("\n");
	//第一个参数是控制行,第二个参数才是控制列
	

	int x = 0, y = 0;
	int k = 0;//步数索引
	int round = 0;

	Point path[100];//路径
	int flag[100][100];//是否走过
	int dir[100] = { 0 }; //搜索方向
	Point delta[4];//偏移量
	flag[0][0] = 1;
	while (true) {
		//0,0 第一列第0行
		//左边 0,-1 第0行第1列
		//右边 0,1 第0行第1列
		//上边 -1,0 第-1行第0列
		//下边 1,0 第1行第0列
		round = 0;//重置遍历次数
		//左方 0
		delta[0].x = x;
		delta[0].y = y - 1;
		//上方 1
		delta[1].x = x - 1;
		delta[1].y = y;
		//右方 2
		delta[2].x = x;
		delta[2].y = y + 1;
		//下方 3
		delta[3].x = x + 1;
		delta[3].y = y;
		for (int i = 0; i < 4; i++) {
			//不超出迷宫边界,即不小于0,不大于行/列
			if (delta[i].x >= 0 && delta[i].y >= 0 && delta[i].x < max_x && delta[i].y < max_y) {
				//不是墙,即所在格子值不为1
				
				if (maze_arr[delta[i].x][delta[i].y] != 1) {
					//没走过,即所在格子的flag值不为1
					if (flag[delta[i].x][delta[i].y] != 1) {
						
						//将偏移量delta加到当前坐标上
						x = delta[i].x;
						y = delta[i].y;
						path[k].x = x;
						path[k].y = y;
						//记录当前的搜索方向dir
						dir[k] = i;
						k++;
						//将当前位置的flag值标为1,表示已走
						flag[x][y] = 1;
						//是否最后一步
						if (x == max_x - 1 && y == max_y - 1) {
							//输出坐标
							printf("<0,0>\n");
							for (int j = 0; j < 100; j++) {
									if (path[j].x >= 0) {
										printf("<%d,%d>\n", path[j].x, path[j].y);
									}
							}
							return 0;
						}
						break;
					}
				}
			}
			round++;
		}
		
		if (round == 4) {
			//将当前坐标的搜索方向dir重置为0
			dir[k] = 0;
			path[k].x = 0;
			path[k].y = 0;
			//将当前坐标回退到上一步
			
			switch (dir[k-1]) {
			case 0:
				y++;
				break;
			case 1:
				x++;
				break;
			case 2:
				y--;
				break;
			case 3:
				x--;
				break;
			}
			if (k - 1 < 0) {
				printf("No solution!\n");
				break;
			}
			//令上一步的搜索方向加1(不然会重复上一次的方向)
			dir[k - 1]++;
			//回退到上一步,即让k减1
			k--;
		}

	}
	return 0;
}

运行截图

无解决方案
有解决方案

来源

华南理工大学广州学院 – 林煜东 linyd@gcu.edu.com

[小程序] 活力健身房

简介

一款基于手机加速度传感器的跑步记录小程序。
用步伐丈量世界,在活力健身房记录你的跑步轨迹,助你更快达成你的跑步目标。
运动海报,记录每一天的变化,分享好友相互勉励,在活力健身房健身不再是孤独的坚持。

小程序码

截图

仓库地址

PS

这次开发的这个小程序其实就是Lebu的升级版本,算法上升级到了2.0,计算算法更加准确且高效。加入了轨迹图,逐公里的配速曲线以及逐公里的海拔曲线。还支持运动信息海报生成。终于是把在Lebu上没实现的功能都开发完成了,开心owo

PPS

华南赛区三等奖

第一次参加只能当个混子,拿个三等奖了。希望明年能够有更好的成绩吧!