342 lines
9.2 KiB
Python
342 lines
9.2 KiB
Python
#!/usr/bin/env python
|
|
# -*- coding: utf-8 -*-
|
|
|
|
import csv
|
|
import argparse
|
|
from clint.textui import puts, colored, indent
|
|
from clint.textui import columns
|
|
#import pytz
|
|
#import tzlocal
|
|
import time
|
|
from datetime import datetime, timedelta, date
|
|
import dateutil.parser
|
|
from dateutil.rrule import rrulestr
|
|
#from icalendar import Calendar,Event,Todo,Journal,Alarm
|
|
#import caldav
|
|
#import uuid
|
|
#import json
|
|
import os
|
|
#os.environ['LANGUAGE']='fr'
|
|
#import logging
|
|
import sys
|
|
#import re
|
|
#import urllib3
|
|
#from getpass import getpass
|
|
#from sympy import symbols
|
|
#from sympy.plotting import textplot
|
|
import subprocess
|
|
from subprocess import Popen, PIPE
|
|
import numpy as np
|
|
import gettext
|
|
#gettext.bindtextdomain('base', 'locale/en/LC_MESSAGES/base.mo')
|
|
#gettext.textdomain('base')
|
|
# Voir : https://docs.python.org/fr/3/library/gettext.html
|
|
en = gettext.translation('base', localedir='locale/', languages=['en'])
|
|
en.install()
|
|
_ = en.gettext # english
|
|
# fr = gettext.translation('base', localedir='locale/', languages=['fr'])
|
|
# fr.install()
|
|
# _ = fr.gettext # english
|
|
# Voir : https://medium.com/i18n-and-l10n-resources-for-developers/how-to-translate-python-applications-with-the-gnu-gettext-module-5c1c085041
|
|
|
|
"""
|
|
This program allow you to store and visualise your weight.
|
|
No database is necessary because all is stored in files.
|
|
Three files are important :
|
|
- weight-cli.py, the principal program
|
|
- data2.csv, the data file and
|
|
- Fonctionnel.txt, the code for Gnuplot
|
|
But other files are present, as personal.txt with your other
|
|
parameters.
|
|
|
|
A measure is characterized by :
|
|
- its value
|
|
- its type
|
|
- its date
|
|
- its metrics
|
|
- its identifier
|
|
- one comment
|
|
- other
|
|
|
|
Actually, weight-cli allow to add or remove a measure,
|
|
visualise all the measure, plot a graph of these.
|
|
|
|
To know witch parameters are available, type :
|
|
weight-cli --help or weight-cli -h
|
|
"""
|
|
|
|
def save_file_data():
|
|
""" Saving the data file name """
|
|
f = open("Fonctionnel.txt", "r")
|
|
contents = f.readlines()
|
|
f.close()
|
|
linenum = 0
|
|
for row in contents:
|
|
if row.split(' ',1)[0] == 'plot':
|
|
contents.insert(linenum, "plot '"+args.data+"' using 3:1 pt '.' title '', f(x) lt 7 title 'bmi'\n")
|
|
del(contents[linenum+1])
|
|
linenum += 1
|
|
f = open("Fonctionnel.txt", "w")
|
|
contents = "".join(contents)
|
|
f.write(contents)
|
|
f.close()
|
|
|
|
def save_mesure():
|
|
""" Displaying and recording a measure """
|
|
print(_("Your measure has been recorded"))
|
|
with indent(4, quote=colored.blue('')):
|
|
puts(colored.green("-your weight : {weight} kg").format(weight=args.weight))
|
|
puts("-its type : {typ}".format(typ=args.type))
|
|
puts("-the date : {dat}".format(dat=args.date))
|
|
puts("-the metric : {metric}".format(metric=args.metric))
|
|
puts("-the identifier : {ide}".format(ide=args.id))
|
|
puts("-your comment : {comment}".format(comment=args.comment))
|
|
puts("-other : {other}".format(other=args.other))
|
|
with open(str(args.data), 'a', newline='\n') as csvfile:
|
|
weightwriter = csv.writer(csvfile, delimiter='|', quotechar='"', quoting=csv.QUOTE_MINIMAL)
|
|
weightwriter.writerow([str(args.weight), \
|
|
str(args.type), \
|
|
str(datetime.now().strftime("%Y-%m-%d %H:%M:%S")), \
|
|
str(args.metric), str(args.id), \
|
|
str(args.comment), \
|
|
str(args.other)])
|
|
|
|
def read_measures():
|
|
""" Display of all measures """
|
|
data_file = open(str(args.data), 'r')
|
|
data = csv.reader(data_file, delimiter='|')
|
|
linenum = 0
|
|
for row in data:
|
|
with indent(2, quote=colored.blue('')):
|
|
puts(columns([(colored.red(str(linenum))), 4], \
|
|
[(colored.green(str(row[0])+' kg')), 15], \
|
|
[(str(row[1])),10], \
|
|
[(colored.yellow(str(row[2]))),25], \
|
|
[(str(row[3])),6], \
|
|
[(str(row[4])),4], \
|
|
[(colored.magenta(str(row[5]))),20])), \
|
|
[(str(row[6])),10]
|
|
linenum += 1
|
|
data_file.close()
|
|
|
|
def remove_measure():
|
|
""" Remove a measure """
|
|
f = open(args.data, "r")
|
|
contents = f.readlines()
|
|
f.close()
|
|
# remove the line item from list, by line number, starts from 0
|
|
store_temp = str(args.remove)+' '+contents[args.remove]
|
|
g = open('remove.txt', "w")
|
|
g.write(str(store_temp))
|
|
g.close()
|
|
contents.pop(args.remove)
|
|
|
|
f = open(args.data, "w")
|
|
contents = "".join(contents)
|
|
f.write(contents)
|
|
f.close()
|
|
|
|
def undo_remove():
|
|
""" Undo remove the last line removed """
|
|
f = open(args.data, "r")
|
|
contents = f.readlines()
|
|
f.close()
|
|
g = open('remove.txt', 'r')
|
|
store_temp = g.readline().split(' ',1)
|
|
g.close()
|
|
# insert the line item from list, by its line number
|
|
contents.insert(int(store_temp[0]), store_temp[1])
|
|
|
|
f = open(args.data, "w")
|
|
contents = "".join(contents)
|
|
f.write(contents)
|
|
f.close()
|
|
|
|
def plot_graph():
|
|
""" Plot the graph of the weight evolution with Gnuplot """
|
|
if args.dates != None:
|
|
print(args.dates)
|
|
# set xrange [*:*]
|
|
f = open("Fonctionnel.txt", "r")
|
|
contents = f.readlines()
|
|
f.close()
|
|
linenum = 0
|
|
for row in contents:
|
|
motif = row.split(' ',2)[0]+' '+row.split(' ',2)[1]
|
|
if motif == 'set xrange':
|
|
if args.dates[0] == '*':
|
|
ligne = "set xrange [*:'"+args.dates[1]+"']\n"
|
|
elif args.dates[1] == '*':
|
|
ligne = "set xrange ['"+args.dates[0]+"':*]\n"
|
|
else:
|
|
ligne = "set xrange ['"+args.dates[0]+"':'"+args.dates[1]+"']\n"
|
|
contents.insert(linenum, ligne)
|
|
del(contents[linenum+1])
|
|
linenum += 1
|
|
f = open("Fonctionnel.txt", "w")
|
|
contents = "".join(contents)
|
|
f.write(contents)
|
|
f.close()
|
|
else:
|
|
f = open("Fonctionnel.txt", "r")
|
|
contents = f.readlines()
|
|
f.close()
|
|
linenum = 0
|
|
for row in contents:
|
|
motif = row.split(' ',2)[0]+' '+row.split(' ',2)[1]
|
|
if motif == 'set xrange':
|
|
contents.insert(linenum, "set xrange [*:*]\n")
|
|
del(contents[linenum+1])
|
|
linenum += 1
|
|
f = open("Fonctionnel.txt", "w")
|
|
contents = "".join(contents)
|
|
f.write(contents)
|
|
f.close()
|
|
#process = Popen(['gnuplot', 'Fonctionnel.txt'], stdout=PIPE, stderr=PIPE)
|
|
process = Popen(['gnuplot', 'Fonctionnel.txt'])#, stdout=PIPE, stderr=PIPE)
|
|
stdout, stderr = process.communicate()
|
|
#print(stdout)
|
|
|
|
def save_size():
|
|
print(bmi_weight_max())
|
|
""" Store the size """
|
|
f = open('personal.txt', "w")
|
|
f.write(str(args.size))
|
|
f.close()
|
|
|
|
f = open("Fonctionnel.txt", "r")
|
|
contents = f.readlines()
|
|
f.close()
|
|
linenum = 0
|
|
for row in contents:
|
|
motif = row.split(' ',2)[0]+' '+row.split(' ',2)[1]
|
|
if motif == 'f(x) =':
|
|
contents.insert(linenum, "f(x) = "+str(bmi_weight_max())+"\n")
|
|
del(contents[linenum+1])
|
|
linenum += 1
|
|
f = open("Fonctionnel.txt", "w")
|
|
contents = "".join(contents)
|
|
f.write(contents)
|
|
f.close()
|
|
|
|
def tests_subproc():
|
|
""" Test of the subprocess module """
|
|
process = Popen(['cat', 'data2.csv'], stdout=PIPE, stderr=PIPE)
|
|
stdout, stderr = process.communicate()
|
|
print(stdout)
|
|
|
|
def bmi(the_weight):
|
|
""" Return the BMI for a given size """
|
|
f = open('personal.txt', "r")
|
|
the_size = float(f.read())
|
|
f.close()
|
|
bmi = the_weight / pow(the_size, 2)
|
|
return(bmi)
|
|
|
|
def bmi_weight_max():
|
|
""" Return the weight for BMI max """
|
|
f = open('personal.txt', "r")
|
|
the_size = float(f.read())
|
|
f.close()
|
|
weight_max = 29.9 * pow(the_size, 2)
|
|
return(weight_max)
|
|
|
|
### Main ###
|
|
""" Weight Recording Program
|
|
Be careful, the data.csv file has a header line that lacks
|
|
a final | separator for the number of fields to be correct.
|
|
"""
|
|
|
|
# Creating the parser for arguments
|
|
parser = argparse.ArgumentParser()
|
|
texte = _('A script to manage your weight in command line.')
|
|
parser.description=texte
|
|
# Creating arguments
|
|
parser.add_argument('-da', '--data',
|
|
default='data.csv',
|
|
help=_('optional : file data')
|
|
)
|
|
parser.add_argument('-s', '--size',
|
|
type=float,
|
|
default=-1,
|
|
help=_('optional : size in meter')
|
|
)
|
|
parser.add_argument('-w', '--weight',
|
|
type=float,
|
|
default=-1,
|
|
help=_('optional : weight in kilogram')
|
|
)
|
|
parser.add_argument('-t', '--type',
|
|
default='WEIGHT',
|
|
help=_('optional : type')
|
|
)
|
|
parser.add_argument('-d', '--date',
|
|
default=datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
|
|
help=_('optional : date')
|
|
)
|
|
parser.add_argument('-i', '--id',
|
|
default='',
|
|
help=_('optional : id')
|
|
)
|
|
parser.add_argument('-m', '--metric',
|
|
default='true',
|
|
help=_('optional : metric')
|
|
)
|
|
parser.add_argument('-c', '--comment',
|
|
default=' ',
|
|
help=_('optional : comment')
|
|
)
|
|
parser.add_argument('-o', '--other',
|
|
default='',
|
|
help=_('optional : other')
|
|
)
|
|
parser.add_argument('-r', '--read',
|
|
help='optional read measures',
|
|
action='store_true'
|
|
)
|
|
parser.add_argument('-rem', '--remove',
|
|
type=int,
|
|
default='-1',
|
|
help=_('optional : delete a measure by its number in the list')
|
|
)
|
|
parser.add_argument('-g', '--graph',
|
|
help=_('optional : plot graph'),
|
|
action='store_true'
|
|
)
|
|
parser.add_argument('-ds', '--dates',
|
|
nargs='+',
|
|
help=_("optional : min_date max_date -> 'Y-m-d hh:mm:ss' or '*' for an automatic date.")
|
|
)
|
|
parser.add_argument('-tst', '--tests',
|
|
help='optional tests operations',
|
|
action='store_true'
|
|
)
|
|
parser.add_argument('-ur', '--undoremove',
|
|
help=_('optional : undo remove the last line removed'),
|
|
action='store_true'
|
|
)
|
|
parser.add_argument('-v', '--version',
|
|
version='0.0.5',
|
|
action='version'
|
|
)
|
|
# Argument retrieval
|
|
args = parser.parse_args()
|
|
# Launching of actions
|
|
if args.data != 'data2.csv':
|
|
save_file_data()
|
|
if args.size != -1:
|
|
save_size()
|
|
if args.weight != -1:
|
|
save_mesure()
|
|
if args.read:
|
|
read_measures()
|
|
if args.remove >= 0:
|
|
remove_measure()
|
|
if args.graph:
|
|
plot_graph()
|
|
if args.tests:
|
|
tests_subproc()
|
|
if args.undoremove:
|
|
undo_remove()
|
|
|