Added unit format options and updated the CI.

This commit is contained in:
Teal Dulcet 2023-05-11 07:03:53 -07:00
parent 3608b85963
commit cb2440f1ab
8 changed files with 482 additions and 156 deletions

View File

@ -36,6 +36,34 @@ jobs:
- name: Clang-Tidy - name: Clang-Tidy
run: clang-tidy -checks='bugprone-*,-bugprone-easily-swappable-parameters,cert-*,clang-analyzer-*,misc-const-correctness,misc-redundant-expression,misc-unused-*,modernize-*,-modernize-use-trailing-return-type,performance-*,portability-*,readability-const-return-type,readability-container-*,readability-duplicate-include,readability-else-after-return,readability-non-const-parameter,readability-redundant-*,readability-simplify-*,readability-string-compare,readability-use-anyofallof' -header-filter='.*' *.cpp -- -Wall -O3 -std=c++17 run: clang-tidy -checks='bugprone-*,-bugprone-easily-swappable-parameters,cert-*,clang-analyzer-*,misc-const-correctness,misc-redundant-expression,misc-unused-*,modernize-*,-modernize-use-trailing-return-type,performance-*,portability-*,readability-const-return-type,readability-container-*,readability-duplicate-include,readability-else-after-return,readability-non-const-parameter,readability-redundant-*,readability-simplify-*,readability-string-compare,readability-use-anyofallof' -header-filter='.*' *.cpp -- -Wall -O3 -std=c++17
Pylint:
name: Pylint
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Install dependencies
run: |
python3 -m pip install --upgrade pip
python3 -m pip install pylint
- name: Script
run: pylint -f colorized --py-version 3.7 -d design,C0103,W0311,C0301,C0302,C0209 --load-plugins pylint.extensions.code_style,pylint.extensions.emptystring,pylint.extensions.comparetozero,pylint.extensions.comparison_placement,pylint.extensions.for_any_all,pylint.extensions.consider_refactoring_into_while_condition,pylint.extensions.consider_ternary_expression,pylint.extensions.dict_init_mutate,pylint.extensions.docstyle,pylint.extensions.check_elif,pylint.extensions.set_membership,pylint.extensions.typing -e R6104 -r y python/*.py
continue-on-error: true
Ruff:
name: Ruff
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Install dependencies
run: |
python3 -m pip install --upgrade pip
python3 -m pip install ruff
- name: Script
run: ruff --format=github --target-version py37 --select F,E,W,I,D,UP,YTT,S,BLE,B,A,C4,T10,EM,EXE,ISC,ICN,G,PIE,PYI,Q,RSE,RET,SLF,SIM,TID,TCH,ARG,PGH,PL,RUF --ignore E101,E501,W191,D211,D213,D401,PLR09,PLR2004,RUF003 .
continue-on-error: true
Python: Python:
name: Linux Python name: Linux Python

View File

@ -1,7 +1,7 @@
[![Build Status](https://travis-ci.com/tdulcet/Tables-and-Graphs.svg?branch=master)](https://travis-ci.com/tdulcet/Tables-and-Graphs) [![Build Status](https://travis-ci.com/tdulcet/Tables-and-Graphs.svg?branch=master)](https://travis-ci.com/tdulcet/Tables-and-Graphs)
[![Actions Status](https://github.com/tdulcet/Table-and-Graph-Libs/workflows/CI/badge.svg?branch=master)](https://github.com/tdulcet/Table-and-Graph-Libs/actions) [![Actions Status](https://github.com/tdulcet/Table-and-Graph-Libs/workflows/CI/badge.svg?branch=master)](https://github.com/tdulcet/Table-and-Graph-Libs/actions)
# Tables and Graphs # Table and Graph Libraries
Console Table and Graph/Plot Libraries Console Table and Graph/Plot Libraries
@ -759,19 +759,42 @@ Default value: `true`
Requires `axis` to be `true`. Requires `axis` to be `true`.
#### Axis ticks #### Axis tick marks
Option: `axistick`\ Option: `axistick`\
Default value: `true` Default value: `true`
Requires `axis` and `axislabel` to be `true`. Requires `axis` to be `true`.
#### Axis units labels #### Axis units labels
Option: `axisunitslabel`\ Option: `axisunitslabel`\
Default value: `true` Default value: `true`
Requires `axis`, `axislabel` and `axistick` to be `true`. Requires `axis` and `axistick` to be `true`.
#### X-axis units format
Option: `xunits`\
Values:
1. `units_number`: Locale number format
2. `units_scale_none`: Locale number format with full precision
3. `units_scale_SI`: Auto-scale to the SI standard
4. `units_scale_IEC`: Auto-scale to the IEC standard
5. `units_scale_IEC_I`: Auto-scale to the IEC standard
6. `units_fracts`: Locale number format, but convert fractions and mathematical constants to Unicode characters (default)
6. `units_percent`: Percentage format
7. `units_date`: Locale date format
8. `units_time`: Locale time format
9. `units_monetary`: Locale monetary/currency format
Formats 2-5 are similar to the respective `--to` options with the [numfmt](https://www.gnu.org/software/coreutils/manual/html_node/numfmt-invocation.html) command from GNU Coreutils, but with [more precision](https://github.com/tdulcet/Numbers-Tool#comparison-of---to-option).
#### Y-axis units format
Option: `yunits`\
Values: Same as above.
#### Title #### Title

View File

@ -15,6 +15,7 @@
#include <iterator> #include <iterator>
#include <numeric> #include <numeric>
#include <functional> #include <functional>
#include <chrono>
#include <sys/ioctl.h> #include <sys/ioctl.h>
#include <unistd.h> #include <unistd.h>
@ -81,6 +82,24 @@ namespace graphs
const char *const constants[] = {"π", "e"}; const char *const constants[] = {"π", "e"};
const long double constantvalues[] = {M_PI, M_E}; const long double constantvalues[] = {M_PI, M_E};
enum units_type
{
units_number,
units_scale_none,
units_scale_SI,
units_scale_IEC,
units_scale_IEC_I,
units_fracts,
units_percent,
units_date,
units_time,
units_monetary
};
enum units_type const units_types[] = {units_number, units_scale_SI, units_scale_IEC, units_scale_IEC_I, units_fracts, units_percent, units_date, units_time, units_monetary};
const char *const suffix_power_char[] = {"", "K", "M", "G", "T", "P", "E", "Z", "Y", "R", "Q"};
const long double max_bit = scalbn(1.0L, LDBL_MANT_DIG - 1); const long double max_bit = scalbn(1.0L, LDBL_MANT_DIG - 1);
const long double MAX = max_bit + (max_bit - 1); const long double MAX = max_bit + (max_bit - 1);
@ -91,6 +110,8 @@ namespace graphs
bool axislabel = true; bool axislabel = true;
bool axistick = true; bool axistick = true;
bool axisunitslabel = true; bool axisunitslabel = true;
units_type xunits = units_fracts;
units_type yunits = units_fracts;
const char *title = nullptr; const char *title = nullptr;
style_type style = style_light; style_type style = style_light;
color_type color = color_red; color_type color = color_red;
@ -114,7 +135,7 @@ namespace graphs
if (iscntrl(str[i])) if (iscntrl(str[i]))
{ {
cerr << "\nError! Control character in string.\n"; cerr << "\nError! Control character in string.\n";
cout << "Control character: " << (int)str[i] << "\n"; cout << "Control character: " << (int)str[i] << '\n';
} }
length = mbstowcs(nullptr, str, 0); length = mbstowcs(nullptr, str, 0);
@ -200,8 +221,90 @@ namespace graphs
return wrapped; return wrapped;
} }
// Auto-scale number to unit
// Adapted from: https://github.com/coreutils/coreutils/blob/master/src/numfmt.c
void outputunit(long double number, const units_type scale, ostringstream &strm)
{
unsigned int x = 0;
long double val = number;
if (val >= -LDBL_MAX and val <= LDBL_MAX)
{
while (abs(val) >= 10)
{
++x;
val /= 10;
}
}
if (scale == units_scale_none)
{
if (x > LDBL_DIG)
return;
strm << setprecision(LDBL_DIG) << number;
return;
}
if (x > 33 - 1)
return;
double scale_base;
switch (scale)
{
case units_scale_IEC:
case units_scale_IEC_I:
scale_base = 1024;
break;
case units_scale_none:
case units_scale_SI:
default:
scale_base = 1000;
break;
}
unsigned int power = 0;
if (number >= -LDBL_MAX and number <= LDBL_MAX)
{
while (abs(number) >= scale_base)
{
++power;
number /= scale_base;
}
}
long double anumber = abs(number);
anumber += anumber < 10 ? 0.0005 : anumber < 100 ? 0.005
: anumber < 1000 ? 0.05
: 0.5;
if (number != 0 and anumber < 1000 and power > 0)
{
strm << setprecision(LDBL_DIG) << number;
string str = strm.str();
const unsigned int length = 5 + (number < 0 ? 1 : 0);
if (str.length() > length)
{
const int prec = anumber < 10 ? 3 : anumber < 100 ? 2
: 1;
strm.str("");
strm << setprecision(prec) << fixed << number;
}
}
else
{
strm << setprecision(0) << fixed << number;
}
strm << (power < graphs::size(suffix_power_char) ? suffix_power_char[power] : "(error)");
if (scale == units_scale_IEC_I and power > 0)
strm << "i";
}
// Convert fractions and constants to Unicode characters // Convert fractions and constants to Unicode characters
size_t outputfraction(const long double number, ostringstream &strm) void outputfraction(const long double number, ostringstream &strm)
{ {
bool output = false; bool output = false;
@ -249,6 +352,49 @@ namespace graphs
if (!output) if (!output)
strm << number; strm << number;
}
size_t outputlabel(const long double label, const units_type units, ostringstream &strm)
{
strm.imbue(locale(""));
switch (units)
{
case units_number:
strm << label;
break;
case units_scale_none:
case units_scale_SI:
case units_scale_IEC:
case units_scale_IEC_I:
outputunit(label, units, strm);
break;
case units_fracts:
outputfraction(label, strm);
break;
case units_percent:
strm << label * 100 << '%';
break;
case units_date:
{
// const time_t t = chrono::system_clock::to_time_t(chrono::sys_seconds(chrono::duration_cast<chrono::seconds>(chrono::duration<double>(label))));
const time_t t = chrono::system_clock::to_time_t(chrono::system_clock::time_point(chrono::duration_cast<chrono::seconds>(chrono::duration<long double>(label))));
const tm atm = *localtime(&t);
strm << put_time(&atm, "%x");
break;
}
case units_time:
{
// const time_t t = chrono::system_clock::to_time_t(chrono::sys_seconds(chrono::duration_cast<chrono::seconds>(chrono::duration<double>(label))));
const time_t t = chrono::system_clock::to_time_t(chrono::system_clock::time_point(chrono::duration_cast<chrono::seconds>(chrono::duration<long double>(label))));
const tm atm = *localtime(&t);
strm << put_time(&atm, "%X");
break;
}
case units_monetary:
strm << showbase << put_money(label);
break;
}
size_t length = strcol(strm.str().c_str()); size_t length = strcol(strm.str().c_str());
@ -320,7 +466,7 @@ namespace graphs
setlocale(LC_ALL, ""); setlocale(LC_ALL, "");
if (title and title[0] != '\0') if (title and title[0] != '\0')
cout << wrap(title, awidth) << "\n"; cout << wrap(title, awidth) << '\n';
if (border) if (border)
{ {
@ -329,7 +475,7 @@ namespace graphs
for (size_t k = 0; k < awidth; ++k) for (size_t k = 0; k < awidth; ++k)
cout << styles[style][0]; cout << styles[style][0];
cout << styles[style][4] << "\n"; cout << styles[style][4] << '\n';
} }
for (size_t i = 0; i < height; i += 4) for (size_t i = 0; i < height; i += 4)
@ -340,7 +486,7 @@ namespace graphs
ostringstream ylabelstrm; ostringstream ylabelstrm;
size_t ylabellength = 0; size_t ylabellength = 0;
if (axis and axislabel and axistick and axisunitslabel and yaxis >= 0 and yaxis <= height) if (axis and axistick and axisunitslabel and yaxis >= 0 and yaxis <= height)
{ {
bool output = false; bool output = false;
long double label = 0; long double label = 0;
@ -358,7 +504,7 @@ namespace graphs
if (output) if (output)
{ {
ylabellength = outputfraction(label, ylabelstrm); ylabellength = outputlabel(label, aoptions.yunits, ylabelstrm);
ylabellength *= 2; ylabellength *= 2;
} }
} }
@ -392,7 +538,7 @@ namespace graphs
cout << styles[style][10]; cout << styles[style][10];
output = true; output = true;
} }
else if (axislabel and axistick) else if (axistick)
{ {
int adivisor = i < yaxis ? -ydivisor : ydivisor; int adivisor = i < yaxis ? -ydivisor : ydivisor;
@ -423,7 +569,7 @@ namespace graphs
cout << styles[style][4]; cout << styles[style][4];
output = true; output = true;
} }
else if (axislabel and axistick) else if (axistick)
{ {
int adivisor = j < xaxis ? -xdivisor : xdivisor; int adivisor = j < xaxis ? -xdivisor : xdivisor;
@ -442,7 +588,7 @@ namespace graphs
output = true; output = true;
} }
} }
else if (yaxislabel and xaxislabel and axislabel and axistick and axisunitslabel and ymin <= 0 and ymax >= 0 and xmin <= 0 and xmax >= 0) else if (yaxislabel and xaxislabel and axistick and axisunitslabel and ymin <= 0 and ymax >= 0 and xmin <= 0 and xmax >= 0)
{ {
cout << "0"; cout << "0";
output = true; output = true;
@ -452,7 +598,7 @@ namespace graphs
cout << "x"; cout << "x";
output = true; output = true;
} }
else if (yaxislabel and axislabel and axistick and axisunitslabel) else if (yaxislabel and axistick and axisunitslabel)
{ {
long double label = 0; long double label = 0;
int adivisor = j < xaxis ? -xdivisor : xdivisor; int adivisor = j < xaxis ? -xdivisor : xdivisor;
@ -477,7 +623,7 @@ namespace graphs
output = false; output = false;
ostringstream strm; ostringstream strm;
size_t length = outputfraction(label, strm); size_t length = outputlabel(label, aoptions.xunits, strm);
length *= 2; length *= 2;
if ((j >= xaxis or (j + length) < (ymin <= 0 and ymax >= 0 and xmin <= 0 and xmax >= 0 ? xaxis - 4 : xaxis)) and (j + length) < (width - 2) and (xaxis <= (width - 2) or j > 2)) if ((j >= xaxis or (j + length) < (ymin <= 0 and ymax >= 0 and xmin <= 0 and xmax >= 0 ? xaxis - 4 : xaxis)) and (j + length) < (width - 2) and (xaxis <= (width - 2) or j > 2))
{ {
@ -498,7 +644,7 @@ namespace graphs
cout << "y"; cout << "y";
output = true; output = true;
} }
else if (ylabellength and (xaxis < 2 ? xaxislabel : j < (xaxis - ylabellength) and (j + 2) >= (xaxis - ylabellength)) and (yaxis >= 4 or i < (height - 4)) and axislabel and axistick and axisunitslabel) else if (ylabellength and (xaxis < 2 ? xaxislabel : j < (xaxis - ylabellength) and (j + 2) >= (xaxis - ylabellength)) and (yaxis >= 4 or i < (height - 4)) and axistick and axisunitslabel)
{ {
cout << ylabelstrm.str(); cout << ylabelstrm.str();
output = true; output = true;
@ -546,7 +692,7 @@ namespace graphs
cout << styles[style][1]; cout << styles[style][1];
if (i < (height - 4) or border) if (i < (height - 4) or border)
cout << "\n"; cout << '\n';
} }
if (border) if (border)

View File

@ -10,7 +10,13 @@
### Usage ### Usage
Requires Python 3.6 or greater and the [wcwidth library](https://pypi.org/project/wcwidth/), which users can install with: `pip3 install wcwidth`. See the [tables.py](tables.py) file for full usage information. Requires Python 3.6 or greater and the [wcwidth library](https://pypi.org/project/wcwidth/), which users can install with:
```bash
pip3 install wcwidth
# or
python3 -m pip install wcwidth
```
See the [tables.py](tables.py) file for full usage information.
Complete versions of all of the examples below and more can be found in the [test.py](test.py) file. Complete versions of all of the examples below and more can be found in the [test.py](test.py) file.
@ -231,7 +237,13 @@ Check that the width of the table is not greater then the width of the terminal.
### Usage ### Usage
Requires Python 3.6 or greater and the [wcwidth library](https://pypi.org/project/wcwidth/), which users can install with: `pip3 install wcwidth`. See the [graphs.py](graphs.py) file for full usage information. Requires Python 3.6 or greater and the [wcwidth library](https://pypi.org/project/wcwidth/), which users can install with:
```bash
pip3 install wcwidth
# or
python3 -m pip install wcwidth
```
See the [graphs.py](graphs.py) file for full usage information.
Complete versions of all of the examples below and more can be found in the [test.py](test.py) file. Complete versions of all of the examples below and more can be found in the [test.py](test.py) file.
@ -371,19 +383,42 @@ Default value: `True`
Requires `axis` to be `True`. Requires `axis` to be `True`.
#### Axis ticks #### Axis tick marks
Option: `axistick`\ Option: `axistick`\
Default value: `True` Default value: `True`
Requires `axis` and `axislabel` to be `True`. Requires `axis` to be `True`.
#### Axis units labels #### Axis units labels
Option: `axisunitslabel`\ Option: `axisunitslabel`\
Default value: `True` Default value: `True`
Requires `axis`, `axislabel` and `axistick` to be `True`. Requires `axis` and `axistick` to be `True`.
#### X-axis units format
Option: `xunits`\
Values:
1. `units_types.number`: Locale number format
2. `units_types.scale_none`: Locale number format with full precision
3. `units_types.scale_SI`: Auto-scale to the SI standard
4. `units_types.scale_IEC`: Auto-scale to the IEC standard
5. `units_types.scale_IEC_I`: Auto-scale to the IEC standard
6. `units_types.fracts`: Locale number format, but convert fractions and mathematical constants to Unicode characters (default)
7. `units_types.percent`: Percentage format
8. `units_types.date`: Locale date format
9. `units_types.time`: Locale time format
10. `units_types.monetary`: Locale monetary/currency format
Formats 2-5 are similar to the respective `--to` options with the [numfmt](https://www.gnu.org/software/coreutils/manual/html_node/numfmt-invocation.html) command from GNU Coreutils, but with [more precision](https://github.com/tdulcet/Numbers-Tool#comparison-of---to-option).
#### Y-axis units format
Option: `yunits`\
Values: Same as above.
#### Title #### Title

View File

@ -1,20 +1,20 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
# -*- coding: utf-8 -*-
# Teal Dulcet, CS546 # Teal Dulcet, CS546
from __future__ import division, print_function, unicode_literals import locale
import sys
import math import math
import shutil import shutil
from fractions import Fraction import sys
import textwrap import textwrap
from datetime import datetime, timezone
from enum import Enum, IntEnum, auto from enum import Enum, IntEnum, auto
from wcwidth import wcswidth from fractions import Fraction
from typing import List, Tuple, Optional, Sequence, Callable from typing import Callable, List, Optional, Sequence, Tuple
import locale
locale.setlocale(locale.LC_ALL, '') from wcwidth import wcswidth
locale.setlocale(locale.LC_ALL, "")
class style_types(IntEnum): class style_types(IntEnum):
@ -112,6 +112,22 @@ constants = {
"e": math.e "e": math.e
} }
class units_types(Enum):
number = auto()
scale_none = auto()
scale_SI = auto()
scale_IEC = auto()
scale_IEC_I = auto()
fracts = auto()
percent = auto()
date = auto()
time = auto()
monetary = auto()
suffix_power_char = ["", "K", "M", "G", "T", "P", "E", "Z", "Y", "R", "Q"]
MAX = sys.float_info.radix ** sys.float_info.mant_dig - 1 MAX = sys.float_info.radix ** sys.float_info.mant_dig - 1
@ -127,8 +143,60 @@ def strcol(astr: str) -> int:
# return len(astr) # return len(astr)
def outputfraction(number: float) -> Tuple[int, str]: def outputunit(number: float, scale: units_types) -> str:
"""Convert fractions and constants to Unicode characters""" x = 0
val = number
if -sys.float_info.max <= val <= sys.float_info.max:
while abs(val) >= 10:
x += 1
val /= 10
if scale == units_types.scale_none:
if x > sys.float_info.dig:
return ""
return f"{number:.{sys.float_info.dig}n}"
if x > 33 - 1:
return ""
if scale in {units_types.scale_IEC, units_types.scale_IEC_I}:
scale_base = 1024
elif scale == units_types.scale_SI:
scale_base = 1000
power = 0
if -sys.float_info.max <= number <= sys.float_info.max:
while abs(number) >= scale_base:
power += 1
number /= scale_base
anumber = abs(number)
anumber += 0.0005 if anumber < 10 else 0.005 if anumber < 100 else 0.05 if anumber < 1000 else 0.5
strm = ""
if number != 0 and anumber < 1000 and power > 0:
strm = f"{number:.{sys.float_info.dig}n}"
length = 5 + (number < 0)
if len(strm) > length:
prec = 3 if anumber < 10 else 2 if anumber < 100 else 1
strm = locale.format_string(f"%.{prec}f", number, grouping=True)
else:
strm = locale.format_string("%.0f", number, grouping=True)
strm += suffix_power_char[power] if power < len(
suffix_power_char) else "(error)"
if scale == units_types.scale_IEC_I and power > 0:
strm += "i"
return strm
def outputfraction(number: float) -> str:
"""Convert fractions and constants to Unicode characters."""
output = False output = False
strm = "" strm = ""
@ -145,7 +213,7 @@ def outputfraction(number: float) -> Tuple[int, str]:
if intpart == 0 and number < 0: if intpart == 0 and number < 0:
strm += "-" strm += "-"
elif intpart != 0: elif intpart != 0:
strm += "{0:n}".format(intpart) strm += f"{intpart:n}"
strm += fraction strm += fraction
@ -160,8 +228,7 @@ def outputfraction(number: float) -> Tuple[int, str]:
if intpart == -1: if intpart == -1:
strm += "-" strm += "-"
elif intpart != 1: elif intpart != 1:
strm += "{0:.{prec}n}".format(intpart, strm += f"{intpart:.{sys.float_info.dig}n}"
prec=sys.float_info.dig)
strm += constant strm += constant
@ -169,7 +236,27 @@ def outputfraction(number: float) -> Tuple[int, str]:
break break
if not output: if not output:
strm += "{0:n}".format(number) strm += f"{number:n}"
return strm
def outputlabel(label: float, units: units_types) -> Tuple[int, str]:
"""Outputs a label in a nice, human readable format."""
if units == units_types.number:
strm = f"{label:n}"
elif units in {units_types.scale_none, units_types.scale_SI, units_types.scale_IEC, units_types.scale_IEC_I}:
strm = outputunit(label, units)
elif units == units_types.fracts:
strm = outputfraction(label)
elif units == units_types.percent:
strm = f"{label:%}"
elif units == units_types.date:
strm = datetime.fromtimestamp(label, timezone.utc).strftime("%x")
elif units == units_types.time:
strm = datetime.fromtimestamp(label, timezone.utc).strftime("%X")
elif units == units_types.monetary:
strm = locale.currency(label, grouping=True)
length = strcol(strm) length = strcol(strm)
@ -177,8 +264,8 @@ def outputfraction(number: float) -> Tuple[int, str]:
def graph(height: int, width: int, xmin: float, xmax: float, ymin: float, ymax: float, array: List[List[int]], border: bool = False, axis: bool = True, axislabel: bool = True, axistick: bool = True, def graph(height: int, width: int, xmin: float, xmax: float, ymin: float, ymax: float, array: List[List[int]], border: bool = False, axis: bool = True, axislabel: bool = True, axistick: bool = True,
axisunitslabel: bool = True, style: style_types = style_types.light, title: Optional[str] = None, check: bool = True) -> int: axisunitslabel: bool = True, xunits: units_types = units_types.fracts, yunits: units_types = units_types.fracts, style: style_types = style_types.light, title: Optional[str] = None, check: bool = True) -> int:
"""Output graph""" """Output graph."""
if not array: if not array:
return 1 return 1
@ -195,13 +282,13 @@ def graph(height: int, width: int, xmin: float, xmax: float, ymin: float, ymax:
if check: if check:
if aheight > w.lines: if aheight > w.lines:
print("The height of the graph ({0}) is greater then the height of the terminal ({1}).".format( print(
aheight, w.lines), file=sys.stderr) f"The height of the graph ({aheight}) is greater then the height of the terminal ({w.lines}).", file=sys.stderr)
return 1 return 1
if awidth > w.columns: if awidth > w.columns:
print("The width of the graph ({0}) is greater then the width of the terminal ({1}).".format( print(
awidth, w.columns), file=sys.stderr) f"The width of the graph ({awidth}) is greater then the width of the terminal ({w.columns}).", file=sys.stderr)
return 1 return 1
if xmin >= xmax: if xmin >= xmax:
@ -233,29 +320,27 @@ def graph(height: int, width: int, xmin: float, xmax: float, ymin: float, ymax:
i = 0 i = 0
while i < height: while i < height:
ayaxis = i <= yaxis and i + 4 > yaxis if yaxis <= height - \ ayaxis = i <= yaxis < i + 4 if yaxis <= height - 4 else i < yaxis <= i + 4
4 else i < yaxis and i + 4 >= yaxis yaxislabel = i <= yaxis + 4 < i + 4 if yaxis <= height - 4 else i < yaxis - 4 <= i + 4
yaxislabel = i <= yaxis + 4 and i + 4 > yaxis + \
4 if yaxis <= height - 4 else i < yaxis - 4 and i + 4 >= yaxis
ylabelstrm = "" ylabelstrm = ""
ylabellength = 0 ylabellength = 0
if axis and axislabel and axistick and axisunitslabel and yaxis >= 0 and yaxis <= height: if axis and axistick and axisunitslabel and 0 <= yaxis <= height:
output = False output = False
label = 0.0 label = 0.0
adivisor = -ydivisor if i < yaxis else ydivisor adivisor = -ydivisor if i < yaxis else ydivisor
k = yaxis + adivisor k = yaxis + adivisor
while (k >= i if i < yaxis else k < i + 4) and i >= 4 and not output: while (k >= i if i < yaxis else k < i + 4) and i >= 4 and not output:
if i <= k and i + 4 > k: if i <= k < i + 4:
label = ymax - (height if k > height else k) * ystep label = ymax - (height if k > height else k) * ystep
output = True output = True
k += adivisor k += adivisor
if output: if output:
ylabellength, ylabelstrm = outputfraction(label) ylabellength, ylabelstrm = outputlabel(label, yunits)
ylabellength *= 2 ylabellength *= 2
if border: if border:
@ -263,9 +348,8 @@ def graph(height: int, width: int, xmin: float, xmax: float, ymin: float, ymax:
j = 0 j = 0
while j < width: while j < width:
axaxis = j < xaxis and j + 2 >= xaxis if xaxis >= 2 else j <= xaxis and j + 2 > xaxis axaxis = j < xaxis <= j + 2 if xaxis >= 2 else j <= xaxis < j + 2
xaxislabel = j < xaxis - 2 and j + 2 >= xaxis - \ xaxislabel = j < xaxis - 2 <= j + 2 if xaxis >= 2 else j <= xaxis + 2 < j + 2
2 if xaxis >= 2 else j <= xaxis + 2 and j + 2 > xaxis + 2
output = False output = False
@ -280,12 +364,12 @@ def graph(height: int, width: int, xmin: float, xmax: float, ymin: float, ymax:
elif i >= height - 4: elif i >= height - 4:
strm += styles[style][10] strm += styles[style][10]
output = True output = True
elif axislabel and axistick: elif axistick:
adivisor = -ydivisor if i < yaxis else ydivisor adivisor = -ydivisor if i < yaxis else ydivisor
k = yaxis + adivisor k = yaxis + adivisor
while (k >= i if i < yaxis else k < i + 4) and i >= 4 and not output: while (k >= i if i < yaxis else k < i + 4) and i >= 4 and not output:
if i <= k and i + 4 > k: if i <= k < i + 4:
strm += styles[style][7 if xaxis >= 2 else 5] strm += styles[style][7 if xaxis >= 2 else 5]
output = True output = True
k += adivisor k += adivisor
@ -299,12 +383,12 @@ def graph(height: int, width: int, xmin: float, xmax: float, ymin: float, ymax:
elif j >= width - 2: elif j >= width - 2:
strm += styles[style][4] strm += styles[style][4]
output = True output = True
elif axislabel and axistick: elif axistick:
adivisor = -xdivisor if j < xaxis else xdivisor adivisor = -xdivisor if j < xaxis else xdivisor
k = xaxis + adivisor k = xaxis + adivisor
while (k >= j if j < xaxis else k < j + 2) and j < width - 4 and not output: while (k >= j if j < xaxis else k < j + 2) and j < width - 4 and not output:
if j <= k and j + 2 > k: if j <= k < j + 2:
strm += styles[style][3 if yaxis <= strm += styles[style][3 if yaxis <=
height - 4 else 9] height - 4 else 9]
output = True output = True
@ -312,13 +396,13 @@ def graph(height: int, width: int, xmin: float, xmax: float, ymin: float, ymax:
if not output: if not output:
strm += styles[style][0] strm += styles[style][0]
output = True output = True
elif yaxislabel and xaxislabel and axislabel and axistick and axisunitslabel and ymin <= 0 and ymax >= 0 and xmin <= 0 and xmax >= 0: elif yaxislabel and xaxislabel and axistick and axisunitslabel and ymin <= 0 <= ymax and xmin <= 0 <= xmax:
strm += "0" strm += "0"
output = True output = True
elif (j >= width - 2 if xaxis <= width - 2 else j == 0) and yaxislabel and axislabel: elif (j >= width - 2 if xaxis <= width - 2 else j == 0) and yaxislabel and axislabel:
strm += "x" strm += "x"
output = True output = True
elif yaxislabel and axislabel and axistick and axisunitslabel: elif yaxislabel and axistick and axisunitslabel:
label = 0.0 label = 0.0
adivisor = -xdivisor if j < xaxis else xdivisor adivisor = -xdivisor if j < xaxis else xdivisor
if j < xaxis: if j < xaxis:
@ -326,7 +410,7 @@ def graph(height: int, width: int, xmin: float, xmax: float, ymin: float, ymax:
k = xaxis + adivisor k = xaxis + adivisor
while (k >= j if j < xaxis else k < j + 2) and j < width - 2 and not output: while (k >= j if j < xaxis else k < j + 2) and j < width - 2 and not output:
if j <= k and j + 2 > k: if j <= k < j + 2:
label = (width if k > width else k) * xstep + xmin label = (width if k > width else k) * xstep + xmin
output = True output = True
@ -338,7 +422,7 @@ def graph(height: int, width: int, xmin: float, xmax: float, ymin: float, ymax:
if output: if output:
output = False output = False
length, astrm = outputfraction(label) length, astrm = outputlabel(label, xunits)
length *= 2 length *= 2
if (j >= xaxis or j + length < xaxis - 4) and j + length < width - 2: if (j >= xaxis or j + length < xaxis - 4) and j + length < width - 2:
strm += astrm strm += astrm
@ -353,7 +437,7 @@ def graph(height: int, width: int, xmin: float, xmax: float, ymin: float, ymax:
elif (i == 0 if yaxis >= 4 else i >= height - 4) and xaxislabel and axislabel: elif (i == 0 if yaxis >= 4 else i >= height - 4) and xaxislabel and axislabel:
strm += "y" strm += "y"
output = True output = True
elif ylabellength and (xaxislabel if xaxis < 2 else j < xaxis - ylabellength and j + 2 >= xaxis - ylabellength) and (yaxis >= 4 or i < height - 4) and axislabel and axistick and axisunitslabel: elif ylabellength and (xaxislabel if xaxis < 2 else j < xaxis - ylabellength and j + 2 >= xaxis - ylabellength) and (yaxis >= 4 or i < height - 4) and axistick and axisunitslabel:
strm += ylabelstrm strm += ylabelstrm
output = True output = True
if ylabellength > 2: if ylabellength > 2:
@ -405,8 +489,8 @@ def graph(height: int, width: int, xmin: float, xmax: float, ymin: float, ymax:
def arrays(height: int, width: int, xmin: float, xmax: float, ymin: float, ymax: float, aarrays: Sequence[Sequence[Sequence[float]]], border: bool = False, axis: bool = True, axislabel: bool = True, axistick: bool = True, axisunitslabel: bool = True, def arrays(height: int, width: int, xmin: float, xmax: float, ymin: float, ymax: float, aarrays: Sequence[Sequence[Sequence[float]]], border: bool = False, axis: bool = True, axislabel: bool = True, axistick: bool = True, axisunitslabel: bool = True,
style: style_types = style_types.light, color: color_types = color_types.red, title: Optional[str] = None, check: bool = True) -> int: xunits: units_types = units_types.fracts, yunits: units_types = units_types.fracts, style: style_types = style_types.light, color: color_types = color_types.red, title: Optional[str] = None, check: bool = True) -> int:
"""Convert one or more arrays to graph and output""" """Convert one or more arrays to graph and output."""
if not aarrays: if not aarrays:
return 1 return 1
@ -427,13 +511,13 @@ def arrays(height: int, width: int, xmin: float, xmax: float, ymin: float, ymax:
awidth = width // 2 awidth = width // 2
if aheight > w.lines: if aheight > w.lines:
print("The height of the graph ({0}) is greater then the height of the terminal ({1}).".format( print(
aheight, w.lines), file=sys.stderr) f"The height of the graph ({aheight}) is greater then the height of the terminal ({w.lines}).", file=sys.stderr)
return 1 return 1
if awidth > w.columns: if awidth > w.columns:
print("The width of the graph ({0}) is greater then the width of the terminal ({1}).".format( print(
awidth, w.columns), file=sys.stderr) f"The width of the graph ({awidth}) is greater then the width of the terminal ({w.columns}).", file=sys.stderr)
return 1 return 1
if xmin == 0 and xmax == 0: if xmin == 0 and xmax == 0:
@ -474,19 +558,19 @@ def arrays(height: int, width: int, xmin: float, xmax: float, ymin: float, ymax:
aaarray[x][y] = acolor aaarray[x][y] = acolor
return graph(height, width, xmin, xmax, ymin, ymax, aaarray, border=border, axis=axis, axislabel=axislabel, return graph(height, width, xmin, xmax, ymin, ymax, aaarray, border=border, axis=axis, axislabel=axislabel,
axistick=axistick, axisunitslabel=axisunitslabel, style=style, title=title) axistick=axistick, axisunitslabel=axisunitslabel, xunits=xunits, yunits=yunits, style=style, title=title)
def array(height: int, width: int, xmin: float, xmax: float, ymin: float, ymax: float, aarray: Sequence[Sequence[float]], border: bool = False, axis: bool = True, axislabel: bool = True, axistick: bool = True, def array(height: int, width: int, xmin: float, xmax: float, ymin: float, ymax: float, aarray: Sequence[Sequence[float]], border: bool = False, axis: bool = True, axislabel: bool = True, axistick: bool = True,
axisunitslabel: bool = True, style: style_types = style_types.light, color: color_types = color_types.red, title: Optional[str] = None) -> int: axisunitslabel: bool = True, xunits: units_types = units_types.fracts, yunits: units_types = units_types.fracts, style: style_types = style_types.light, color: color_types = color_types.red, title: Optional[str] = None) -> int:
"""Convert single array to graph and output""" """Convert single array to graph and output."""
return arrays(height, width, xmin, xmax, ymin, ymax, [aarray], border=border, axis=axis, axislabel=axislabel, return arrays(height, width, xmin, xmax, ymin, ymax, [aarray], border=border, axis=axis, axislabel=axislabel,
axistick=axistick, axisunitslabel=axisunitslabel, style=style, color=color, title=title) axistick=axistick, axisunitslabel=axisunitslabel, xunits=xunits, yunits=yunits, style=style, color=color, title=title)
def functions(height: int, width: int, xmin: float, xmax: float, ymin: float, ymax: float, afunctions: Sequence[Callable[[float], float]], border: bool = False, axis: bool = True, axislabel: bool = True, axistick: bool = True, def functions(height: int, width: int, xmin: float, xmax: float, ymin: float, ymax: float, afunctions: Sequence[Callable[[float], float]], border: bool = False, axis: bool = True, axislabel: bool = True, axistick: bool = True,
axisunitslabel: bool = True, style: style_types = style_types.light, color: color_types = color_types.red, title: Optional[str] = None, check: bool = True) -> int: axisunitslabel: bool = True, xunits: units_types = units_types.fracts, yunits: units_types = units_types.fracts, style: style_types = style_types.light, color: color_types = color_types.red, title: Optional[str] = None, check: bool = True) -> int:
"""Convert one or more functions to graph and output""" """Convert one or more functions to graph and output."""
if not afunctions: if not afunctions:
return 1 return 1
@ -503,13 +587,13 @@ def functions(height: int, width: int, xmin: float, xmax: float, ymin: float, ym
awidth = width // 2 awidth = width // 2
if aheight > w.lines: if aheight > w.lines:
print("The height of the graph ({0}) is greater then the height of the terminal ({1}).".format( print(
aheight, w.lines), file=sys.stderr) f"The height of the graph ({aheight}) is greater then the height of the terminal ({w.lines}).", file=sys.stderr)
return 1 return 1
if awidth > w.columns: if awidth > w.columns:
print("The width of the graph ({0}) is greater then the width of the terminal ({1}).".format( print(
awidth, w.columns), file=sys.stderr) f"The width of the graph ({awidth}) is greater then the width of the terminal ({w.columns}).", file=sys.stderr)
return 1 return 1
if xmin >= xmax: if xmin >= xmax:
@ -538,7 +622,7 @@ def functions(height: int, width: int, xmin: float, xmax: float, ymin: float, ym
x = i * xstep + xmin x = i * xstep + xmin
y = function(x) y = function(x)
if x >= xmin and x < xmax and y >= ymin and y < ymax: if xmin <= x < xmax and ymin <= y < ymax:
ax = int(x / xstep + xaxis) ax = int(x / xstep + xaxis)
ay = int(yaxis - y / ystep - 1) ay = int(yaxis - y / ystep - 1)
@ -549,11 +633,11 @@ def functions(height: int, width: int, xmin: float, xmax: float, ymin: float, ym
array[ax][ay] = acolor array[ax][ay] = acolor
return graph(height, width, xmin, xmax, ymin, ymax, array, border=border, axis=axis, axislabel=axislabel, return graph(height, width, xmin, xmax, ymin, ymax, array, border=border, axis=axis, axislabel=axislabel,
axistick=axistick, axisunitslabel=axisunitslabel, style=style, title=title) axistick=axistick, axisunitslabel=axisunitslabel, xunits=xunits, yunits=yunits, style=style, title=title)
def function(height, width, xmin: float, xmax: float, ymin: float, ymax: float, afunction: Callable[[float], float], border: bool = False, axis: bool = True, axislabel: bool = True, axistick: bool = True, def function(height: int, width: int, xmin: float, xmax: float, ymin: float, ymax: float, afunction: Callable[[float], float], border: bool = False, axis: bool = True, axislabel: bool = True, axistick: bool = True,
axisunitslabel: bool = True, style: style_types = style_types.light, color: color_types = color_types.red, title: Optional[str] = None) -> int: axisunitslabel: bool = True, xunits: units_types = units_types.fracts, yunits: units_types = units_types.fracts, style: style_types = style_types.light, color: color_types = color_types.red, title: Optional[str] = None) -> int:
"""Convert single function to function array and output""" """Convert single function to function array and output."""
return functions(height, width, xmin, xmax, ymin, ymax, [afunction], border=border, axis=axis, axislabel=axislabel, return functions(height, width, xmin, xmax, ymin, ymax, [afunction], border=border, axis=axis, axislabel=axislabel,
axistick=axistick, axisunitslabel=axisunitslabel, style=style, color=color, title=title) axistick=axistick, axisunitslabel=axisunitslabel, xunits=xunits, yunits=yunits, style=style, color=color, title=title)

View File

@ -1,19 +1,18 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
# -*- coding: utf-8 -*-
# Teal Dulcet, CS546 # Teal Dulcet, CS546
from __future__ import division, print_function, unicode_literals import locale
import sys
import shutil
import re import re
import shutil
import sys
import textwrap import textwrap
from enum import IntEnum, auto from enum import IntEnum, auto
from wcwidth import wcswidth from typing import Any, Callable, List, Optional, Sequence
from typing import List, Optional, Any, Sequence, Callable
import locale
locale.setlocale(locale.LC_ALL, '') from wcwidth import wcswidth
locale.setlocale(locale.LC_ALL, "")
class style_types(IntEnum): class style_types(IntEnum):
@ -37,12 +36,12 @@ styles = [
# [" ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " "]] #No border # [" ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " "]] #No border
] ]
ansi = re.compile(r'\x1B\[(?:[0-9]+(?:;[0-9]+)*)?m') ansi = re.compile(r"\x1B\[(?:[0-9]+(?:;[0-9]+)*)?m")
def strcol(astr: str) -> int: def strcol(astr: str) -> int:
"""Returns the number of columns that the given string would take up if printed.""" """Returns the number of columns that the given string would take up if printed."""
astr = ansi.sub('', astr) astr = ansi.sub("", astr)
width = wcswidth(astr) width = wcswidth(astr)
if width == -1: if width == -1:
print( print(
@ -55,7 +54,7 @@ def strcol(astr: str) -> int:
def table(array: List[List[str]], headerrow: bool = False, headercolumn: bool = False, tableborder: bool = True, cellborder: bool = False, def table(array: List[List[str]], headerrow: bool = False, headercolumn: bool = False, tableborder: bool = True, cellborder: bool = False,
padding: int = 1, alignment: Optional[bool] = None, title: Optional[str] = None, style: style_types = style_types.light, check: bool = True) -> int: padding: int = 1, alignment: Optional[bool] = None, title: Optional[str] = None, style: style_types = style_types.light, check: bool = True) -> int:
"""Output char array as table""" """Output char array as table."""
if not array: if not array:
return 1 return 1
@ -75,8 +74,8 @@ def table(array: List[List[str]], headerrow: bool = False, headercolumn: bool =
if check: if check:
if width > w.columns: if width > w.columns:
print("The width of the table ({0}) is greater then the width of the terminal ({1}).".format( print(
width, w.columns), file=sys.stderr) f"The width of the table ({width}) is greater then the width of the terminal ({w.columns}).", file=sys.stderr)
return 1 return 1
if title: if title:
@ -120,7 +119,7 @@ def table(array: List[List[str]], headerrow: bool = False, headercolumn: bool =
strm += " " * padding strm += " " * padding
if alignment is None: if alignment is None:
strm += "{0:{width}}".format(array[i][j], width=awidth) strm += f"{array[i][j]:{awidth}}"
elif alignment: elif alignment:
strm += array[i][j].rjust(awidth) strm += array[i][j].rjust(awidth)
else: else:
@ -134,46 +133,49 @@ def table(array: List[List[str]], headerrow: bool = False, headercolumn: bool =
if i < rows - 1 or tableborder: if i < rows - 1 or tableborder:
strm += "\n" strm += "\n"
if tableborder: if (i < rows - 1 and cellborder) or (i == 0 and headerrow) or (i < rows - 1 and headercolumn):
if i == rows - 1: if tableborder and (cellborder or (i == 0 and headerrow) or headercolumn):
strm += styles[style][8]
elif cellborder or (i == 0 and headerrow) or headercolumn:
strm += styles[style][5] strm += styles[style][5]
if (i == rows - 1 and tableborder) or (i < rows - 1 and cellborder) or (i == 0 and headerrow) or (i < rows - 1 and headercolumn):
for j in range(columns): for j in range(columns):
if (i == rows - 1 and tableborder) or (i < rows - 1 and cellborder) or (i == 0 and headerrow) or (i < rows - 1 and j == 0 and headercolumn): if cellborder or (i == 0 and headerrow) or (j == 0 and headercolumn):
strm += styles[style][0] * (2 * padding + columnwidth[j]) strm += styles[style][0] * (2 * padding + columnwidth[j])
elif i < rows - 1 and headercolumn: elif headercolumn:
strm += " " * (2 * padding + columnwidth[j]) strm += " " * (2 * padding + columnwidth[j])
if j < columns - 1: if j < columns - 1:
if i == rows - 1 and tableborder: if cellborder or ((i == 0 and headerrow) and (j == 0 and headercolumn)):
if cellborder or (j == 0 and headercolumn):
strm += styles[style][9]
else:
strm += styles[style][0]
elif (i < rows - 1 and cellborder) or ((i == 0 and headerrow) and (j == 0 and headercolumn)):
strm += styles[style][6] strm += styles[style][6]
elif i == 0 and headerrow: elif i == 0 and headerrow:
strm += styles[style][9] strm += styles[style][9]
elif i < rows - 1 and headercolumn: elif headercolumn:
if j == 0: if j == 0:
strm += styles[style][7] strm += styles[style][7]
else: else:
strm += " " strm += " "
if tableborder: if tableborder:
if i == rows - 1: if cellborder or (i == 0 and headerrow):
strm += styles[style][10]
elif cellborder or (i == 0 and headerrow):
strm += styles[style][7] strm += styles[style][7]
elif headercolumn: elif headercolumn:
strm += styles[style][1] strm += styles[style][1]
if i < rows - 1:
strm += "\n" strm += "\n"
if tableborder:
strm += styles[style][8]
for j in range(columns):
strm += styles[style][0] * (2 * padding + columnwidth[j])
if j < columns - 1:
if cellborder or (j == 0 and headercolumn):
strm += styles[style][9]
else:
strm += styles[style][0]
strm += styles[style][10]
print(strm) print(strm)
return 0 return 0
@ -181,7 +183,7 @@ def table(array: List[List[str]], headerrow: bool = False, headercolumn: bool =
def array(aarray: Sequence[Sequence[Any]], aheaderrow: Optional[Sequence[Any]] = None, aheadercolumn: Optional[Sequence[Any]] = None, headerrow: bool = False, headercolumn: bool = False, def array(aarray: Sequence[Sequence[Any]], aheaderrow: Optional[Sequence[Any]] = None, aheadercolumn: Optional[Sequence[Any]] = None, headerrow: bool = False, headercolumn: bool = False,
tableborder: bool = True, cellborder: bool = False, padding: int = 1, alignment: Optional[bool] = None, title: Optional[str] = None, style: style_types = style_types.light) -> int: tableborder: bool = True, cellborder: bool = False, padding: int = 1, alignment: Optional[bool] = None, title: Optional[str] = None, style: style_types = style_types.light) -> int:
"""Convert array to char array and output as table""" """Convert array to char array and output as table."""
if not aarray: if not aarray:
return 1 return 1
@ -232,7 +234,7 @@ def array(aarray: Sequence[Sequence[Any]], aheaderrow: Optional[Sequence[Any]] =
def functions(xmin: float, xmax: float, xstep: float, afunctions: Sequence[Callable[[float], float]], headerrow: bool = False, headercolumn: bool = False, tableborder: bool = True, def functions(xmin: float, xmax: float, xstep: float, afunctions: Sequence[Callable[[float], float]], headerrow: bool = False, headercolumn: bool = False, tableborder: bool = True,
cellborder: bool = False, padding: int = 1, alignment: Optional[bool] = None, title: Optional[str] = None, style: style_types = style_types.light) -> int: cellborder: bool = False, padding: int = 1, alignment: Optional[bool] = None, title: Optional[str] = None, style: style_types = style_types.light) -> int:
"""Convert one or more functions to array and output as table""" """Convert one or more functions to array and output as table."""
if not afunctions: if not afunctions:
return 1 return 1
@ -271,6 +273,6 @@ def functions(xmin: float, xmax: float, xstep: float, afunctions: Sequence[Calla
def function(xmin: float, xmax: float, xstep: float, afunction: Callable[[float], float], headerrow: bool = False, headercolumn: bool = False, tableborder: bool = True, def function(xmin: float, xmax: float, xstep: float, afunction: Callable[[float], float], headerrow: bool = False, headercolumn: bool = False, tableborder: bool = True,
cellborder: bool = False, padding: int = 1, alignment: Optional[bool] = None, title: Optional[str] = None, style: style_types = style_types.light) -> int: cellborder: bool = False, padding: int = 1, alignment: Optional[bool] = None, title: Optional[str] = None, style: style_types = style_types.light) -> int:
"""Convert single function to array and output as table""" """Convert single function to array and output as table."""
return functions(xmin, xmax, xstep, [afunction], headerrow=headerrow, headercolumn=headercolumn, return functions(xmin, xmax, xstep, [afunction], headerrow=headerrow, headercolumn=headercolumn,
tableborder=tableborder, cellborder=cellborder, padding=padding, alignment=alignment, title=title, style=style) tableborder=tableborder, cellborder=cellborder, padding=padding, alignment=alignment, title=title, style=style)

View File

@ -1,25 +1,24 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
# -*- coding: utf-8 -*-
# Teal Dulcet, CS546 # Teal Dulcet, CS546
from __future__ import division, print_function, unicode_literals import math
import random import random
import sys import sys
import math
import graphs import graphs
import tables import tables
def afunction(x): def afunction(x: float):
return x + 1 return x + 1
def function1(x): def function1(x: float):
return 2 * x return 2 * x
def function2(x): def function2(x: float):
return x ** 2 return x ** 2
@ -51,7 +50,7 @@ for style in tables.style_types:
headercolumn=True, style=style) headercolumn=True, style=style)
print("\nOutput array as table with separate header row and column\n") print("\nOutput array as table with separate header row and column\n")
array = [["Data {0:n}".format(i + j) for j in range(4)] array = [[f"Data {i + j:n}" for j in range(4)]
for i in range(1, 4 * 4 + 1, 4)] for i in range(1, 4 * 4 + 1, 4)]
headerrow = ["Header row/column 1", "Header row 2", headerrow = ["Header row/column 1", "Header row 2",
"Header row 3", "Header row 4", "Header row 5"] "Header row 3", "Header row 4", "Header row 5"]

View File

@ -78,7 +78,7 @@ namespace tables
if (iscntrl(str[i])) if (iscntrl(str[i]))
{ {
cerr << "\nError! Control character in string.\n"; cerr << "\nError! Control character in string.\n";
cout << "Control character: " << (int)str[i] << "\n"; cout << "Control character: " << (int)str[i] << '\n';
} }
length = mbstowcs(nullptr, str, 0); length = mbstowcs(nullptr, str, 0);
@ -218,7 +218,7 @@ namespace tables
} }
if (title and title[0] != '\0') if (title and title[0] != '\0')
cout << wrap(title, width) << "\n"; cout << wrap(title, width) << '\n';
if (aoptions.alignment) if (aoptions.alignment)
cout << aoptions.alignment; cout << aoptions.alignment;
@ -241,7 +241,7 @@ namespace tables
} }
} }
cout << styles[style][4] << "\n"; cout << styles[style][4] << '\n';
} }
for (size_t i = 0; i < rows; ++i) for (size_t i = 0; i < rows; ++i)
@ -254,7 +254,7 @@ namespace tables
if ((j and cellborder) or (i == 0 and j and headerrow) or (j == 1 and headercolumn)) if ((j and cellborder) or (i == 0 and j and headerrow) or (j == 1 and headercolumn))
cout << styles[style][1]; cout << styles[style][1];
else if (j and (tableborder or (i and headerrow) or headercolumn)) else if (j and (tableborder or (i and headerrow) or headercolumn))
cout << " "; cout << ' ';
const int difference = columnwidth[j] - strcol(array[i][j].c_str()); const int difference = columnwidth[j] - strcol(array[i][j].c_str());
@ -282,62 +282,71 @@ namespace tables
cout << styles[style][1]; cout << styles[style][1];
if (i < (rows - 1) or tableborder) if (i < (rows - 1) or tableborder)
cout << "\n"; cout << '\n';
if ((i < (rows - 1) and cellborder) or (i == 0 and headerrow) or (i < (rows - 1) and headercolumn))
{
if (tableborder) if (tableborder)
{ {
if (i == (rows - 1)) if (cellborder or (i == 0 and headerrow) or headercolumn)
cout << styles[style][8];
else if (cellborder or (i == 0 and headerrow) or headercolumn)
cout << styles[style][5]; cout << styles[style][5];
} }
if ((i == (rows - 1) and tableborder) or (i < (rows - 1) and cellborder) or (i == 0 and headerrow) or (i < (rows - 1) and headercolumn))
{
for (size_t j = 0; j < columns; ++j) for (size_t j = 0; j < columns; ++j)
{ {
if ((i == (rows - 1) and tableborder) or (i < (rows - 1) and cellborder) or (i == 0 and headerrow) or (i < (rows - 1) and j == 0 and headercolumn)) if (cellborder or (i == 0 and headerrow) or (j == 0 and headercolumn))
for (size_t k = 0; k < (2 * padding) + columnwidth[j]; ++k) for (size_t k = 0; k < (2 * padding) + columnwidth[j]; ++k)
cout << styles[style][0]; cout << styles[style][0];
else if (i < (rows - 1) and headercolumn) else if (headercolumn)
cout << string((2 * padding) + columnwidth[j], ' '); cout << string((2 * padding) + columnwidth[j], ' ');
if (j < (columns - 1)) if (j < (columns - 1))
{ {
if (i == (rows - 1) and tableborder) if (cellborder or ((i == 0 and headerrow) and (j == 0 and headercolumn)))
cout << styles[style][6];
else if (i == 0 and headerrow)
cout << styles[style][9];
else if (headercolumn)
{
if (j == 0)
cout << styles[style][7];
else
cout << ' ';
}
}
}
if (tableborder)
{
if (cellborder or (i == 0 and headerrow))
cout << styles[style][7];
else if (headercolumn)
cout << styles[style][1];
}
cout << '\n';
}
}
if (tableborder)
{
cout << styles[style][8];
for (size_t j = 0; j < columns; ++j)
{
for (size_t k = 0; k < (2 * padding) + columnwidth[j]; ++k)
cout << styles[style][0];
if (j < (columns - 1))
{ {
if (cellborder or (j == 0 and headercolumn)) if (cellborder or (j == 0 and headercolumn))
cout << styles[style][9]; cout << styles[style][9];
else else
cout << styles[style][0]; cout << styles[style][0];
} }
else if ((i < (rows - 1) and cellborder) or ((i == 0 and headerrow) and (j == 0 and headercolumn)))
cout << styles[style][6];
else if (i == 0 and headerrow)
cout << styles[style][9];
else if (i < (rows - 1) and headercolumn)
{
if (j == 0)
cout << styles[style][7];
else
cout << " ";
}
}
} }
if (tableborder)
{
if (i == (rows - 1))
cout << styles[style][10]; cout << styles[style][10];
else if (cellborder or (i == 0 and headerrow))
cout << styles[style][7];
else if (headercolumn)
cout << styles[style][1];
}
if (i < (rows - 1))
cout << "\n";
}
} }
cout << endl; cout << endl;