Pomodoro и chrono. Часть 1

Вопрос управления временем так или иначе волнует каждого работающего человека. Многие знакомы с методом помидора. Если коротко, его суть заключается в специфическом чередовании фиксированных периодов работы и отдыха с учетом отвлекающих факторов. Существует множество приложений, реализующих данную систему. В качестве своеобразного упражнения построим собственное приложение для управления временем.

Задача

Для начала создадим консольное приложение, которое способно с удовлетворительной точностью отсчитывать временные интервалы.

В ранее опубликованной статье для этой задачи использовалась функция time() из ctime. Но так как данная функция может вести себя по разному в зависимости от операционной системы, рекомендуется использовать chrono (для C++). На данной библиотеке и остановимся.

Существует хороший ресурс — https://pomodoro-tracker.com. Всё, что нужно для учета времени по системе pomodoro, там есть. В частности по умолчанию используется схема 25 5 15 4. Это значит, что период работы — 25 минут, перерыв — 5 минут, а после 4-х «помидоров» ( 25 — 5 ) будет «помидор» с перерывом в 15 минут (25 — 15).

Данную схему мы реализуем в своем первом приложении.

Makefile

Назовем программу myPomodoro, в качестве компилятора используем g++, основной исходник — main.cpp.

TARGET = myPomodoro
CC = g++
LIBS = 
CFLAGS = -std=c++11 
OBJ = main.o

app: ${OBJ}
	${CC} ${CFLAGS} ${OBJ} ${LIBS} -o ${TARGET}

main.o: main.cpp
	${CC} ${CFLAGS} -c main.cpp 

clean:
	rm -rf *.o ${TARGET}

«Пустые» переменные нам понадобятся в дальнейшем.

chrono

Для замеров временных промежутков нам нужно знать следующее: состояние таймера в начале отсчета, текущее состояние таймера. Далее остается сравнить количество прошедшего времени с целевым временным интервалом.

Таким образом, используем следующие переменные:


high_resolution_clock::time_point t1;
high_resolution_clock::time_point t2;

Получение текущего момента времени:

t1 = high_resolution_clock::now();

Расчет временного промежутка:

t2 = high_resolution_clock::now();
duration<double> timeSpan = duration_cast<duration<double>>(t2 - t1);
double d = timeSpan.count(); 

С данного момента в переменной d будет храниться длительность временного интервала в секундах.

Ещё одна необходимая деталь — пауза в 1 секунду:

std::this_thread::sleep_for(std::chrono::milliseconds(1000));

Далее остается организовать переключение интервалов «работа-отдых».

main.cpp

#include <iostream>
#include <chrono>
#include <stdio.h>
#include <thread>

using namespace std;
using namespace std::chrono;

int main(int argc, char* argv[]) {

	high_resolution_clock::time_point t1;
	high_resolution_clock::time_point t2;

	double intervals[] = {25*60, 5*60, 15*60};
	const char* names[] = {"Working", "Break", "Long break"};
	char buf[10] = {0};
	int curInt = 0;
	int count = 4;
	bool timerOn = false;

	while(true) {
		if(timerOn) {
			t2 = high_resolution_clock::now();
			duration<double> timeSpan = duration_cast<duration<double>>(t2 - t1);
			double d = timeSpan.count();
			int timeLeft = (int)(intervals[curInt] - d);
			printf("\r%02d:%02d %s              ", timeLeft/60, timeLeft % 60, names[curInt]);
			fflush(stdout);

			if(d >= intervals[curInt]) {
				timerOn = false;
				curInt++;
			} else
				std::this_thread::sleep_for(std::chrono::milliseconds(1000));
		} else {

			if(curInt == 1) {
				if(count <= 0) {
					curInt = 2;
					count = 4;
				};
			} else 	if(curInt == 2 || curInt == 3) {
				while(buf[0] != 'n' && buf[0] != 'y') {
					printf("                          \r");
					printf("Start work? [y/n]");
					scanf("%9s", buf);
				};
				if(buf[0] == 'n') break;
				buf[0] = 0;
				curInt = 0;
				count--;
			};
			
			t1 = high_resolution_clock::now();
			timerOn = true;
		};

	};

  return 0;
};


Заключение

Среди недостатков программы следует отметить отсутствие оповещения пользователя о начале и окончании временного интервала. Но об этом в следующей части.

Добавить комментарий

Ваш e-mail не будет опубликован.