Add basic functionality

This commit is contained in:
Jacob 2019-10-08 17:44:05 +02:00
parent 45c1244ff3
commit 51fed1feb7
15 changed files with 3929 additions and 0 deletions

34
z1-prototype/menu.js Normal file
View File

@ -0,0 +1,34 @@
const VendingMachine = require('./vendingMachine');
let vendingMachine = new VendingMachine();
const readline = require('readline-sync');
function setupMachine() {
vendingMachine.fillMachine();
}
function listProducts() {
const products = vendingMachine.getProducts();
products.forEach((element) => {
if (element.quantity > 0) {
console.log(`${element.id}) ${element.name} - ${element.price}`);
}
});
}
(async () => {
setupMachine();
let credit = readline.question(`Insert coins:\n`);
listProducts();
let id = readline.question(`Choose product from the list:\n`);
let product = vendingMachine.getProductById(id);
if (product.price > credit) {
console.log('Insuficient credit');
} else {
console.log(
'Your change ',
vendingMachine.calculateChange(credit - product.price)
);
console.log('Please take your product');
}
})();

21
z1-prototype/node_modules/readline-sync/LICENSE generated vendored Normal file
View File

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2019 anseki
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@ -0,0 +1,89 @@
# readlineSync
## <a name="deprecated_methods_and_options"></a>Deprecated Methods and Options
The readlineSync current version is fully compatible with older version.
The following methods and options are deprecated.
### <a name="deprecated_methods_and_options-setprint_method"></a>`setPrint` method
Use the [`print`](README.md#basic_options-print) option.
For the [Default Options](README.md#basic_options), use:
```js
readlineSync.setDefaultOptions({print: value});
```
instead of:
```js
readlineSync.setPrint(value);
```
### <a name="deprecated_methods_and_options-setprompt_method"></a>`setPrompt` method
Use the [`prompt`](README.md#basic_options-prompt) option.
For the [Default Options](README.md#basic_options), use:
```js
readlineSync.setDefaultOptions({prompt: value});
```
instead of:
```js
readlineSync.setPrompt(value);
```
### <a name="deprecated_methods_and_options-setencoding_method"></a>`setEncoding` method
Use the [`encoding`](README.md#basic_options-encoding) option.
For the [Default Options](README.md#basic_options), use:
```js
readlineSync.setDefaultOptions({encoding: value});
```
instead of:
```js
readlineSync.setEncoding(value);
```
### <a name="deprecated_methods_and_options-setmask_method"></a>`setMask` method
Use the [`mask`](README.md#basic_options-mask) option.
For the [Default Options](README.md#basic_options), use:
```js
readlineSync.setDefaultOptions({mask: value});
```
instead of:
```js
readlineSync.setMask(value);
```
### <a name="deprecated_methods_and_options-setbuffersize_method"></a>`setBufferSize` method
Use the [`bufferSize`](README.md#basic_options-buffersize) option.
For the [Default Options](README.md#basic_options), use:
```js
readlineSync.setDefaultOptions({bufferSize: value});
```
instead of:
```js
readlineSync.setBufferSize(value);
```
### <a name="deprecated_methods_and_options-noechoback_option"></a>`noEchoBack` option
Use [`hideEchoBack`](README.md#basic_options-hideechoback) option instead of it.
### <a name="deprecated_methods_and_options-notrim_option"></a>`noTrim` option
Use [`keepWhitespace`](README.md#basic_options-keepwhitespace) option instead of it.

1836
z1-prototype/node_modules/readline-sync/README.md generated vendored Normal file

File diff suppressed because it is too large Load Diff

24
z1-prototype/node_modules/readline-sync/lib/encrypt.js generated vendored Normal file
View File

@ -0,0 +1,24 @@
/*
* readlineSync
* https://github.com/anseki/readline-sync
*
* Copyright (c) 2019 anseki
* Licensed under the MIT license.
*/
var cipher = require('crypto').createCipher(
process.argv[2] /*algorithm*/, process.argv[3] /*password*/),
stdin = process.stdin,
stdout = process.stdout,
crypted = '';
stdin.resume();
stdin.setEncoding('utf8');
stdin.on('data', function(d) {
crypted += cipher.update(d, 'utf8', 'hex');
});
stdin.on('end', function() {
stdout.write(crypted + cipher.final('hex'), 'binary', function() {
process.exit(0);
});
});

123
z1-prototype/node_modules/readline-sync/lib/read.cs.js generated vendored Normal file
View File

@ -0,0 +1,123 @@
/* jshint wsh:true */
/*
* readlineSync
* https://github.com/anseki/readline-sync
*
* Copyright (c) 2019 anseki
* Licensed under the MIT license.
*/
var
FSO_ForReading = 1, FSO_ForWriting = 2,
PS_MSG = 'Microsoft Windows PowerShell is required.' +
' https://technet.microsoft.com/en-us/library/hh847837.aspx',
input = '', fso, tty,
options = (function(conf) {
var options = {}, arg, args =// Array.prototype.slice.call(WScript.Arguments),
(function() {
var args = [], i, iLen;
for (i = 0, iLen = WScript.Arguments.length; i < iLen; i++)
{ args.push(WScript.Arguments(i)); }
return args;
})(),
confLc = {}, key;
function decodeArg(arg) {
return arg.replace(/#(\d+);/g, function(str, charCode) {
return String.fromCharCode(+charCode);
});
}
for (key in conf) {
if (conf.hasOwnProperty(key))
{ confLc[key.toLowerCase()] = {key: key, type: conf[key]}; }
}
while (typeof(arg = args.shift()) === 'string') {
if (!(arg = (arg.match(/^\-+(.+)$/) || [])[1])) { continue; }
arg = arg.toLowerCase();
if (confLc[arg]) {
options[confLc[arg].key] =
confLc[arg].type === 'boolean' ? true :
confLc[arg].type === 'string' ? args.shift() : null;
}
}
for (key in conf) {
if (conf.hasOwnProperty(key) && conf[key] === 'string') {
if (typeof options[key] !== 'string') { options[key] = ''; }
else { options[key] = decodeArg(options[key]); }
}
}
return options;
})({
display: 'string',
displayOnly: 'boolean',
keyIn: 'boolean',
hideEchoBack: 'boolean',
mask: 'string'
});
if (!options.hideEchoBack && !options.keyIn) {
if (options.display) { writeTTY(options.display); }
if (!options.displayOnly) { input = readByFSO(); }
} else if (options.hideEchoBack && !options.keyIn && !options.mask) {
if (options.display) { writeTTY(options.display); }
if (!options.displayOnly) { input = readByPW(); }
} else {
WScript.StdErr.WriteLine(PS_MSG);
WScript.Quit(1);
}
WScript.StdOut.Write('\'' + input + '\'');
WScript.Quit();
function writeTTY(text) {
try {
tty = tty || getFso().OpenTextFile('CONOUT$', FSO_ForWriting, true);
tty.Write(text);
} catch (e) {
WScript.StdErr.WriteLine('TTY Write Error: ' + e.number +
'\n' + e.description + '\n' + PS_MSG);
WScript.Quit(e.number || 1);
}
}
function readByFSO() {
var text;
try {
text = getFso().OpenTextFile('CONIN$', FSO_ForReading).ReadLine();
} catch (e) {
WScript.StdErr.WriteLine('TTY Read Error: ' + e.number +
'\n' + e.description + '\n' + PS_MSG);
WScript.Quit(e.number || 1);
}
return text;
}
// TTY must be STDIN that is not redirected and not piped.
function readByPW() {
var text;
try {
text = WScript.CreateObject('ScriptPW.Password').GetPassword()
// Bug? Illegal data may be returned when user types before initializing.
.replace(/[\u4000-\u40FF]/g, function(chr) {
var charCode = chr.charCodeAt(0);
return charCode >= 0x4020 && charCode <= 0x407F ?
String.fromCharCode(charCode - 0x4000) : '';
});
} catch (e) {
WScript.StdErr.WriteLine('ScriptPW.Password Error: ' + e.number +
'\n' + e.description + '\n' + PS_MSG);
WScript.Quit(e.number || 1);
}
writeTTY('\n');
return text;
}
function getFso() {
if (!fso) { fso = new ActiveXObject('Scripting.FileSystemObject'); }
return fso;
}

128
z1-prototype/node_modules/readline-sync/lib/read.ps1 generated vendored Normal file
View File

@ -0,0 +1,128 @@
# readlineSync
# https://github.com/anseki/readline-sync
#
# Copyright (c) 2019 anseki
# Licensed under the MIT license.
Param(
[string] $display,
[switch] $displayOnly,
[switch] $keyIn,
[switch] $hideEchoBack,
[string] $mask,
[string] $limit,
[switch] $caseSensitive
)
$ErrorActionPreference = 'Stop' # for cmdlet
trap {
# `throw $_` and `Write-Error $_` return exit-code 0
$Host.UI.WriteErrorLine($_)
exit 1
}
function decodeArg ($arg) {
[Regex]::Replace($arg, '#(\d+);', { [char][int] $args[0].Groups[1].Value })
}
$options = @{}
foreach ($arg in @('display', 'displayOnly', 'keyIn', 'hideEchoBack', 'mask', 'limit', 'caseSensitive')) {
$options.Add($arg, (Get-Variable $arg -ValueOnly))
}
$argList = New-Object string[] $options.Keys.Count
$options.Keys.CopyTo($argList, 0)
foreach ($arg in $argList) {
if ($options[$arg] -is [string] -and $options[$arg])
{ $options[$arg] = decodeArg $options[$arg] }
}
[string] $inputTTY = ''
[bool] $silent = -not $options.display -and
$options.keyIn -and $options.hideEchoBack -and -not $options.mask
[bool] $isCooked = -not $options.hideEchoBack -and -not $options.keyIn
# Instant method that opens TTY without CreateFile via P/Invoke in .NET Framework
# **NOTE** Don't include special characters of DOS in $command when $getRes is True.
# [string] $cmdPath = $Env:ComSpec
# [string] $psPath = 'powershell.exe'
function execWithTTY ($command, $getRes = $False, $throwError = $False) {
if ($getRes) {
$res = (cmd.exe /C "<CON powershell.exe -Command $command")
if ($LastExitCode -ne 0) {
if ($throwError) { throw $LastExitCode }
else { exit $LastExitCode }
}
return $res
} else {
$command | cmd.exe /C ">CON powershell.exe -Command -"
if ($LastExitCode -ne 0) {
if ($throwError) { throw $LastExitCode }
else { exit $LastExitCode }
}
}
}
function writeTTY ($text) {
execWithTTY ('Write-Host (''' +
(($text -replace '''', '''''') -replace '[\r\n]', '''+"`n"+''') + ''') -NoNewline')
}
if ($options.display) {
writeTTY $options.display
}
if ($options.displayOnly) { return "''" }
if (-not $options.keyIn -and $options.hideEchoBack -and $options.mask -eq '*') {
# It fails when it's not ready.
try {
$inputTTY = execWithTTY ('$text = Read-Host -AsSecureString;' +
'$bstr = [Runtime.InteropServices.Marshal]::SecureStringToBSTR($text);' +
'[Runtime.InteropServices.Marshal]::PtrToStringAuto($bstr)') $True $True
return '''' + $inputTTY + ''''
} catch {} # ignore
}
if ($options.keyIn) { $reqSize = 1 }
if ($options.keyIn -and $options.limit) {
$limitPtn = '[^' + $options.limit + ']'
}
while ($True) {
if (-not $isCooked) {
$chunk = [char][int] (execWithTTY '[int] [Console]::ReadKey($True).KeyChar' $True)
} else {
$chunk = execWithTTY 'Read-Host' $True
$chunk += "`n"
}
if ($chunk -and $chunk -match '^(.*?)[\r\n]') {
$chunk = $Matches[1]
$atEol = $True
} else { $atEol = $False }
# other ctrl-chars
if ($chunk) { $chunk = $chunk -replace '[\x00-\x08\x0b\x0c\x0e-\x1f\x7f]', '' }
if ($chunk -and $limitPtn) {
if ($options.caseSensitive) { $chunk = $chunk -creplace $limitPtn, '' }
else { $chunk = $chunk -ireplace $limitPtn, '' }
}
if ($chunk) {
if (-not $isCooked) {
if (-not $options.hideEchoBack) {
writeTTY $chunk
} elseif ($options.mask) {
writeTTY ($options.mask * $chunk.Length)
}
}
$inputTTY += $chunk
}
if ((-not $options.keyIn -and $atEol) -or
($options.keyIn -and $inputTTY.Length -ge $reqSize)) { break }
}
if (-not $isCooked -and -not $silent) { execWithTTY 'Write-Host ''''' } # new line
return "'$inputTTY'"

137
z1-prototype/node_modules/readline-sync/lib/read.sh generated vendored Normal file
View File

@ -0,0 +1,137 @@
# readlineSync
# https://github.com/anseki/readline-sync
#
# Copyright (c) 2019 anseki
# Licensed under the MIT license.
# Use perl for compatibility of sed/awk of GNU / POSIX, BSD. (and tr)
# Hide "\n" from shell by "\fNL"
decode_arg() {
printf '%s' "$(printf '%s' "$1" | perl -pe 's/#(\d+);/sprintf("%c", $1)/ge; s/[\r\n]/\fNL/g')"
}
# getopt(s)
while [ $# -ge 1 ]; do
arg="$(printf '%s' "$1" | grep -E '^-+[^-]+$' | tr '[A-Z]' '[a-z]' | tr -d '-')"
case "$arg" in
'display') shift; options_display="$(decode_arg "$1")";;
'displayonly') options_displayOnly=true;;
'keyin') options_keyIn=true;;
'hideechoback') options_hideEchoBack=true;;
'mask') shift; options_mask="$(decode_arg "$1")";;
'limit') shift; options_limit="$(decode_arg "$1")";;
'casesensitive') options_caseSensitive=true;;
esac
shift
done
reset_tty() {
if [ -n "$save_tty" ]; then
stty --file=/dev/tty "$save_tty" 2>/dev/null || \
stty -F /dev/tty "$save_tty" 2>/dev/null || \
stty -f /dev/tty "$save_tty" || exit $?
fi
}
trap 'reset_tty' EXIT
save_tty="$(stty --file=/dev/tty -g 2>/dev/null || stty -F /dev/tty -g 2>/dev/null || stty -f /dev/tty -g || exit $?)"
[ -z "$options_display" ] && [ "$options_keyIn" = true ] && \
[ "$options_hideEchoBack" = true ] && [ -z "$options_mask" ] && silent=true
[ "$options_hideEchoBack" != true ] && [ "$options_keyIn" != true ] && is_cooked=true
write_tty() {
# if [ "$2" = true ]; then
# printf '%b' "$1" >/dev/tty
# else
# printf '%s' "$1" >/dev/tty
# fi
printf '%s' "$1" | perl -pe 's/\fNL/\r\n/g' >/dev/tty
}
replace_allchars() { (
text=''
for i in $(seq 1 ${#1})
do
text="$text$2"
done
printf '%s' "$text"
) }
if [ -n "$options_display" ]; then
write_tty "$options_display"
fi
if [ "$options_displayOnly" = true ]; then
printf "'%s'" ''
exit 0
fi
if [ "$is_cooked" = true ]; then
stty --file=/dev/tty cooked 2>/dev/null || \
stty -F /dev/tty cooked 2>/dev/null || \
stty -f /dev/tty cooked || exit $?
else
stty --file=/dev/tty raw -echo 2>/dev/null || \
stty -F /dev/tty raw -echo 2>/dev/null || \
stty -f /dev/tty raw -echo || exit $?
fi
[ "$options_keyIn" = true ] && req_size=1
if [ "$options_keyIn" = true ] && [ -n "$options_limit" ]; then
if [ "$options_caseSensitive" = true ]; then
limit_ptn="$options_limit"
else
# Safe list
# limit_ptn="$(printf '%s' "$options_limit" | sed 's/\([a-z]\)/\L\1\U\1/ig')"
limit_ptn="$(printf '%s' "$options_limit" | perl -pe 's/([a-z])/lc($1) . uc($1)/ige')"
fi
fi
while :
do
if [ "$is_cooked" != true ]; then
# chunk="$(dd if=/dev/tty bs=1 count=1 2>/dev/null)"
chunk="$(dd if=/dev/tty bs=1 count=1 2>/dev/null | perl -pe 's/[\r\n]/\fNL/g')"
else
IFS= read -r chunk </dev/tty || exit $?
chunk="$(printf '%s\fNL' "$chunk")"
fi
# if [ -n "$chunk" ] && [ "$(printf '%s' "$chunk" | tr '\r' '\n' | wc -l)" != "0" ]; then
# chunk="$(printf '%s' "$chunk" | tr '\r' '\n' | head -n 1)"
if [ -n "$chunk" ] && printf '%s' "$chunk" | perl -ne '/\fNL/ or exit 1'; then
chunk="$(printf '%s' "$chunk" | perl -pe 's/^(.*?)\fNL.*$/$1/')"
at_eol=true
fi
# other ctrl-chars
if [ -n "$chunk" ]; then
# chunk="$(printf '%s' "$chunk" | tr -d '\00-\10\13\14\16-\37\177')"
# for System V
chunk="$(printf '%s' "$chunk" | tr -d '\00\01\02\03\04\05\06\07\10\13\14\16\17\20\21\22\23\24\25\26\27\30\31\32\33\34\35\36\37\177')"
fi
if [ -n "$chunk" ] && [ -n "$limit_ptn" ]; then
chunk="$(printf '%s' "$chunk" | tr -cd "$limit_ptn")"
fi
if [ -n "$chunk" ]; then
if [ "$is_cooked" != true ]; then
if [ "$options_hideEchoBack" != true ]; then
write_tty "$chunk"
elif [ -n "$options_mask" ]; then
write_tty "$(replace_allchars "$chunk" "$options_mask")"
fi
fi
input="$input$chunk"
fi
if ( [ "$options_keyIn" != true ] && [ "$at_eol" = true ] ) || \
( [ "$options_keyIn" = true ] && [ ${#input} -ge $req_size ] ); then break; fi
done
if [ "$is_cooked" != true ] && [ "$silent" != true ]; then write_tty "$(printf '%b' '\fNL')"; fi
printf "'%s'" "$input"
exit 0

File diff suppressed because it is too large Load Diff

68
z1-prototype/node_modules/readline-sync/package.json generated vendored Normal file
View File

@ -0,0 +1,68 @@
{
"_from": "readline-sync@^1.4.10",
"_id": "readline-sync@1.4.10",
"_inBundle": false,
"_integrity": "sha512-gNva8/6UAe8QYepIQH/jQ2qn91Qj0B9sYjMBBs3QOB8F2CXcKgLxQaJRP76sWVRQt+QU+8fAkCbCvjjMFu7Ycw==",
"_location": "/readline-sync",
"_phantomChildren": {},
"_requested": {
"type": "range",
"registry": true,
"raw": "readline-sync@^1.4.10",
"name": "readline-sync",
"escapedName": "readline-sync",
"rawSpec": "^1.4.10",
"saveSpec": null,
"fetchSpec": "^1.4.10"
},
"_requiredBy": [
"#USER",
"/"
],
"_resolved": "https://registry.npmjs.org/readline-sync/-/readline-sync-1.4.10.tgz",
"_shasum": "41df7fbb4b6312d673011594145705bf56d8873b",
"_spec": "readline-sync@^1.4.10",
"_where": "/Users/jacob/Documents/University/Rok_3/Semestr_1/Analiza i projektowanie obiektowe/APO_automat/z1-prototype",
"author": {
"name": "anseki",
"url": "https://github.com/anseki"
},
"bugs": {
"url": "https://github.com/anseki/readline-sync/issues"
},
"bundleDependencies": false,
"deprecated": false,
"description": "Synchronous Readline for interactively running to have a conversation with the user via a console(TTY).",
"engines": {
"node": ">= 0.8.0"
},
"files": [
"lib/*.@(js|ps1|sh)",
"README-Deprecated.md"
],
"homepage": "https://github.com/anseki/readline-sync",
"keywords": [
"readline",
"synchronous",
"interactive",
"prompt",
"question",
"password",
"cli",
"tty",
"command",
"repl",
"keyboard",
"wait",
"block"
],
"license": "MIT",
"main": "./lib/readline-sync.js",
"name": "readline-sync",
"repository": {
"type": "git",
"url": "git://github.com/anseki/readline-sync.git"
},
"title": "readlineSync",
"version": "1.4.10"
}

13
z1-prototype/package-lock.json generated Normal file
View File

@ -0,0 +1,13 @@
{
"name": "vending-machine",
"version": "1.0.0",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
"readline-sync": {
"version": "1.4.10",
"resolved": "https://registry.npmjs.org/readline-sync/-/readline-sync-1.4.10.tgz",
"integrity": "sha512-gNva8/6UAe8QYepIQH/jQ2qn91Qj0B9sYjMBBs3QOB8F2CXcKgLxQaJRP76sWVRQt+QU+8fAkCbCvjjMFu7Ycw=="
}
}
}

14
z1-prototype/package.json Normal file
View File

@ -0,0 +1,14 @@
{
"name": "vending-machine",
"version": "1.0.0",
"description": "",
"main": "menu.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC",
"dependencies": {
"readline-sync": "^1.4.10"
}
}

7
z1-prototype/product.js Normal file
View File

@ -0,0 +1,7 @@
module.exports = class Product {
constructor(name, quantity, price) {
this.name = name;
this.quantity = quantity;
this.price = price;
}
};

View File

@ -0,0 +1,27 @@
[
{
"name": "Snickers",
"quantity": 5,
"price": 2.5
},
{
"name": "Mars",
"quantity": 3,
"price": 2
},
{
"name": "Bounty",
"quantity": 7,
"price": 2.25
},
{
"name": "Pepsi",
"quantity": 10,
"price": 3
},
{
"name": "Mirinda",
"quantity": 8,
"price": 3
}
]

View File

@ -0,0 +1,79 @@
const Product = require('./product');
module.exports = class VendingMachine {
constructor() {
this.id = Math.floor(Math.random() * 1000);
this.products = [];
}
addProduct(name, quantity, price) {
if (this.products[name]) {
this.products[name].quantity += quantity;
} else {
if (!price) {
console.error('Price not specified');
return 0;
}
this.products[name] = new Product(name, quantity, price);
}
return this.products[name];
}
buyProduct(id) {
this.products.forEach((product) => {
if (product.id == id) {
product.quantity--;
}
});
}
getProducts() {
return this.products;
}
getProductById(id) {
let product = null;
this.products.forEach((element) => {
if (element.id == id) {
product = element;
}
});
return product;
}
fillMachine() {
this.products = require('./products');
this.enumerateProducts();
}
enumerateProducts() {
let id = 1;
this.products.forEach((item) => (item.id = id++));
}
calculateChange(ammount) {
const availableCoins = [
0.01,
0.02,
0.05,
0.1,
0.2,
0.5,
1,
2,
5
].reverse();
let change = [];
let sum = 0;
while (sum < ammount) {
for (let coin of availableCoins) {
if (sum + coin <= ammount) {
change.push(coin);
break;
}
}
sum = change.reduce((acc, curr) => acc + curr);
}
return change;
}
};