initial commit
commit
b5836f4ae9
|
@ -0,0 +1,5 @@
|
||||||
|
.DS_Store
|
||||||
|
.idea/
|
||||||
|
.gitconfig
|
||||||
|
log.txt
|
||||||
|
result.csv
|
|
@ -0,0 +1,67 @@
|
||||||
|
# Neuffer developers-test
|
||||||
|
|
||||||
|
We have prepared for you simple test task what as we believe, allow us to estimate your experience.
|
||||||
|
It is a small php-script, which should be started in console like:
|
||||||
|
|
||||||
|
`php console.php --action {action} --file {file}`
|
||||||
|
|
||||||
|
Script will take two required parameters:
|
||||||
|
|
||||||
|
`{file}` - csv-source file with numbers, where each row contains two numbers between -100 and 100, and
|
||||||
|
|
||||||
|
`{action}` - what action should we do with numbers from `{file}`, and can take next values:
|
||||||
|
|
||||||
|
* <b>plus</b> - to count summ of the numbers on each row in the {file}
|
||||||
|
* <b>minus</b> - to count difference between first number in the row and second
|
||||||
|
* <b>multiply</b> - to multiply the numbers on each row in the {file}
|
||||||
|
* <b>division</b> - to divide first number in the row and second
|
||||||
|
|
||||||
|
|
||||||
|
As result of the command execution should be csv file with three columns: first number, second number, and result. In CSV-file should be written **ONLY** numbers greater than null. If result less than null - it should be written in logs.
|
||||||
|
|
||||||
|
**Example 1**
|
||||||
|
|
||||||
|
`php console.php --action plus --file {file}`, where in file you can find next numbers:
|
||||||
|
|
||||||
|
10 20 <br/>
|
||||||
|
-30 20 <br/>
|
||||||
|
-3 5 <br/>
|
||||||
|
|
||||||
|
As result in CSV file you should write:
|
||||||
|
|
||||||
|
10 20 30 <br/>
|
||||||
|
-3 5 2
|
||||||
|
|
||||||
|
And in log file, something like "_numbers are - 30 and 20 are wrong_"
|
||||||
|
|
||||||
|
**Example 2**
|
||||||
|
|
||||||
|
`php console.php --action division --file {file}`, where in file you can find next numbers:
|
||||||
|
|
||||||
|
20 10 <br/>
|
||||||
|
-30 20 <br/>
|
||||||
|
3 0 <br/>
|
||||||
|
|
||||||
|
As result in CSV file you should write:
|
||||||
|
|
||||||
|
20 10 2 <br/>
|
||||||
|
|
||||||
|
And in log file, something like:
|
||||||
|
|
||||||
|
_numbers are -30 and 20 are wrong_ <br/>
|
||||||
|
_numbers are 3 and 0 are wrong, is not allowed_ <br/>
|
||||||
|
|
||||||
|
##Task
|
||||||
|
You need to refactor code and write it on proper way. Just do your best: update/delete/add code as you wish.
|
||||||
|
|
||||||
|
After finishing - please push your code in your github/bitbucket account, and send me link back.
|
||||||
|
|
||||||
|
###Requirements
|
||||||
|
|
||||||
|
* After refactoring code shoud work
|
||||||
|
* Code should work on PHP8.0+
|
||||||
|
* As file source example please use test.csv
|
||||||
|
|
||||||
|
###Result
|
||||||
|
Please put result of your work in your Github or Bitbucket account, and send link back.
|
||||||
|
|
|
@ -0,0 +1,46 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
$shortopts = "a:f:";
|
||||||
|
$longopts = array(
|
||||||
|
"action:",
|
||||||
|
"file:",
|
||||||
|
);
|
||||||
|
|
||||||
|
$options = getopt($shortopts, $longopts);
|
||||||
|
|
||||||
|
if(isset($options['a'])) {
|
||||||
|
$action = $options['a'];
|
||||||
|
} elseif(isset($options['action'])) {
|
||||||
|
$action = $options['action'];
|
||||||
|
} else {
|
||||||
|
$action = "xyz";
|
||||||
|
}
|
||||||
|
|
||||||
|
if(isset($options['f'])) {
|
||||||
|
$file = $options['f'];
|
||||||
|
} elseif(isset($options['file'])) {
|
||||||
|
$file = $options['file'];
|
||||||
|
} else {
|
||||||
|
$file = "notexists.csv";
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
if ($action == "plus") {
|
||||||
|
include 'files/ClassOne.php';
|
||||||
|
$classOne = new ClassOne($file);
|
||||||
|
} elseif ($action == "minus") {
|
||||||
|
include 'files/ClassTwo.php';
|
||||||
|
$classTwo = new ClassTwo($file, "minus");
|
||||||
|
$classTwo->start();
|
||||||
|
} elseif ($action == "multiply") {
|
||||||
|
include 'files/Classthree.php';
|
||||||
|
$classThree = new Classthree();
|
||||||
|
$classThree->setFile($file);
|
||||||
|
$classThree->execute();
|
||||||
|
} elseif ($action == "division") {
|
||||||
|
include 'files/classFour.php';
|
||||||
|
$classFouyr = new classFour($file);
|
||||||
|
} else {
|
||||||
|
throw new \Exception("Wrong action is selected");
|
||||||
|
}
|
||||||
|
} catch (\Exception $exception) {}
|
|
@ -0,0 +1,59 @@
|
||||||
|
<?php
|
||||||
|
// we will count sum here
|
||||||
|
class ClassOne
|
||||||
|
{
|
||||||
|
function __construct($file)
|
||||||
|
{
|
||||||
|
$this->start();
|
||||||
|
$fp = fopen($file, "r");
|
||||||
|
$row = 1;
|
||||||
|
while (($data = fgetcsv($fp, 1000, ";")) !== FALSE) {
|
||||||
|
if($this->isGood($data[0], $data[1])) {
|
||||||
|
$this->result($data[0], $data[1]);
|
||||||
|
} else {
|
||||||
|
$this->wrongNumbers($data[0], $data[1]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fclose($fp);
|
||||||
|
$this->stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
function isGood($a, $b)
|
||||||
|
{
|
||||||
|
if($a < 0 && $b < 0) return false;
|
||||||
|
if($a < 0 && (abs($a) > $b)) return false;
|
||||||
|
if($b < 0 && (abs($b) > $a)) return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
function wrongNumbers($a, $b)
|
||||||
|
{
|
||||||
|
$fp = fopen("log.txt", "a+");
|
||||||
|
fwrite($fp, "numbers ".$a . " and ". $b." are wrong \r\n");
|
||||||
|
fclose($fp);
|
||||||
|
}
|
||||||
|
|
||||||
|
function start() {
|
||||||
|
$fp = fopen("log.txt", "w+");
|
||||||
|
fwrite($fp, "Started plus operation \r\n");
|
||||||
|
fclose($fp);
|
||||||
|
}
|
||||||
|
|
||||||
|
function stop() {
|
||||||
|
$fp = fopen("log.txt", "a+");
|
||||||
|
fwrite($fp, "Finished plus operation \r\n");
|
||||||
|
fclose($fp);
|
||||||
|
}
|
||||||
|
|
||||||
|
function result($a, $b)
|
||||||
|
{
|
||||||
|
$a = intval($a);
|
||||||
|
$b = intval($b);
|
||||||
|
$result = $a + $b;
|
||||||
|
$fp = fopen("result.csv", "a+");
|
||||||
|
$data = $a.";".$b.";".$result."\r\n";
|
||||||
|
fwrite($fp, $data);
|
||||||
|
fclose($fp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
?>
|
|
@ -0,0 +1,45 @@
|
||||||
|
<?php
|
||||||
|
//here we will get minus
|
||||||
|
class ClassTwo
|
||||||
|
{
|
||||||
|
private $file;
|
||||||
|
private $action;
|
||||||
|
|
||||||
|
public function __construct($file, $action = "minus")
|
||||||
|
{
|
||||||
|
$this->file = $file;
|
||||||
|
$this->action = $action;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function start()
|
||||||
|
{
|
||||||
|
$fp = fopen("log.txt", "w+");
|
||||||
|
fwrite($fp, "Started minus operation \r\n");
|
||||||
|
|
||||||
|
$data = fopen($this->file, "r");
|
||||||
|
if(!$data) throw new \Exception("File cannot be openned");
|
||||||
|
|
||||||
|
if(file_exists("result.csv")) {
|
||||||
|
unlink("result.csv");
|
||||||
|
}
|
||||||
|
|
||||||
|
while (($line = fgets($data)) !== false) {
|
||||||
|
$line = explode(";", $line);
|
||||||
|
$line[0] = intval($line[0]);
|
||||||
|
$line[1] = intval($line[1]);
|
||||||
|
$result = $line[0] - $line[1];
|
||||||
|
if($result < 0) {
|
||||||
|
fwrite($fp, "numbers ".$line[0] . " and ". $line[1]." are wrong \r\n");
|
||||||
|
} else {
|
||||||
|
$resultHandle = fopen("result.csv", "a+");
|
||||||
|
$result = $line[0].";".$line[1].";".$result."\r\n";
|
||||||
|
fwrite($resultHandle, $result);
|
||||||
|
fclose($resultHandle);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fwrite($fp, "Finished minus operation \r\n");
|
||||||
|
fclose($fp);
|
||||||
|
fclose($data);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,243 @@
|
||||||
|
<?php
|
||||||
|
// here we will make multiplication
|
||||||
|
class Classthree {
|
||||||
|
|
||||||
|
private $file = null;
|
||||||
|
private $resultHandler;
|
||||||
|
private $logHandler;
|
||||||
|
private const LOG_FILE = "log.txt";
|
||||||
|
private const RESULT_FILE = "result.csv";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Classthree constructor.
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
$this->prepareFiles();
|
||||||
|
$this->prepareHanders();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* destructor
|
||||||
|
*/
|
||||||
|
public function __destruct()
|
||||||
|
{
|
||||||
|
$this->closeHandlers();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* main function, execute main code
|
||||||
|
*/
|
||||||
|
public function execute(): void
|
||||||
|
{
|
||||||
|
$this->validateResourceFile();
|
||||||
|
|
||||||
|
$this->logInfo("Started multiply operation");
|
||||||
|
|
||||||
|
$handle = fopen($this->getFile(),'r');
|
||||||
|
while ( ($line = fgetcsv($handle) ) !== FALSE ) {
|
||||||
|
list($value1, $value2) = $this->prepareValues($line[0]);
|
||||||
|
$result = $this->countResult($value1, $value2);
|
||||||
|
if($this->isResultValid($result)) {
|
||||||
|
$this->writeSuccessResult($value1, $value2, $result);
|
||||||
|
} else {
|
||||||
|
$this->wrongResultLog($value1, $value2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->logInfo("Finished multiply operation");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* write in logs if numbers give wrong result
|
||||||
|
* @param int $value1
|
||||||
|
* @param int $value2
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
private function wrongResultLog(int $value1, int $value2) : void
|
||||||
|
{
|
||||||
|
$message = "numbers ".$value1 . " and ". $value2." are wrong";
|
||||||
|
$this->logInfo($message);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* validate if result is valid
|
||||||
|
* @param int $result
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
private function isResultValid(int $result) : bool
|
||||||
|
{
|
||||||
|
if($result > 0)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* count result
|
||||||
|
* @param int $value1
|
||||||
|
* @param int $value2
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
|
private function countResult(int $value1, int $value2) : int
|
||||||
|
{
|
||||||
|
return $value2 * $value1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* prepare numbers before action, explode it from csv string
|
||||||
|
* @param string $line
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
private function prepareValues(string $line) : array
|
||||||
|
{
|
||||||
|
$line = explode(";", $line);
|
||||||
|
$value1 = $this->prepareNumber($line[0]);
|
||||||
|
$value2 = $this->prepareNumber($line[1]);
|
||||||
|
return [$value1, $value2];
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* prepare number before action
|
||||||
|
* @param string $value
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
|
private function prepareNumber(string $value) : int
|
||||||
|
{
|
||||||
|
$value = trim($value);
|
||||||
|
$value = intval($value);
|
||||||
|
return $value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return bool
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
private function validateResourceFile() : void {
|
||||||
|
if($this->getFile() === null) {
|
||||||
|
throw new \Exception("Please define file with data");
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!file_exists($this->getFile())) {
|
||||||
|
throw new \Exception("Please define file with data");
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!is_readable($this->getFile())) {
|
||||||
|
throw new \Exception("We have not rights to read this file");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* check and delete main files before execution
|
||||||
|
*/
|
||||||
|
private function prepareFiles() : void
|
||||||
|
{
|
||||||
|
//delete log file if it is already exists
|
||||||
|
if($this->isLogFileExists()) {
|
||||||
|
unlink(self::LOG_FILE);
|
||||||
|
}
|
||||||
|
|
||||||
|
//delete result file if it already exists
|
||||||
|
if($this->isResultFileExists()) {
|
||||||
|
unlink(self::RESULT_FILE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $file
|
||||||
|
*/
|
||||||
|
public function setFile(string $file): void
|
||||||
|
{
|
||||||
|
$this->file = $file;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getFile() : string
|
||||||
|
{
|
||||||
|
return $this->file;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* check if result file already exists
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
private function isResultFileExists() : bool
|
||||||
|
{
|
||||||
|
return file_exists(self::RESULT_FILE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
private function isLogFileExists() : bool
|
||||||
|
{
|
||||||
|
return file_exists(self::LOG_FILE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* write messages in log file
|
||||||
|
* @param string $message
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
private function logInfo(string $message) : void
|
||||||
|
{
|
||||||
|
$message = $message."\r\n";
|
||||||
|
fwrite($this->logHandler, $message);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* write message in result file
|
||||||
|
* @param string $message
|
||||||
|
*/
|
||||||
|
private function successInfo(string $message) : void
|
||||||
|
{
|
||||||
|
$message = $message."\r\n";
|
||||||
|
fwrite($this->resultHandler, $message);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* prepare info and save it in result file
|
||||||
|
* @param int $value1
|
||||||
|
* @param int $value2
|
||||||
|
* @param int $result
|
||||||
|
*/
|
||||||
|
private function writeSuccessResult(int $value1, int $value2, int $result) : void
|
||||||
|
{
|
||||||
|
$message = implode(";", [$value1, $value2, $result]);
|
||||||
|
$this->successInfo($message);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* prepare handlers to writing
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
private function prepareHanders() : void
|
||||||
|
{
|
||||||
|
$this->logHandler = fopen(self::LOG_FILE, "a+");
|
||||||
|
|
||||||
|
if($this->logHandler === false) {
|
||||||
|
throw new \Exception("Log File cannot be open for writing");
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->resultHandler = fopen(self::RESULT_FILE, "a+");
|
||||||
|
|
||||||
|
if($this->resultHandler === false) {
|
||||||
|
throw new \Exception("Result File cannot be open for writing");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* close opened handlers
|
||||||
|
*/
|
||||||
|
private function closeHandlers() : void
|
||||||
|
{
|
||||||
|
fclose($this->logHandler);
|
||||||
|
fclose($this->resultHandler);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
?>
|
|
@ -0,0 +1,43 @@
|
||||||
|
<?php
|
||||||
|
// here we will make division
|
||||||
|
class classFour{
|
||||||
|
|
||||||
|
public function __construct($file)
|
||||||
|
{
|
||||||
|
if(file_exists("log.txt")) {
|
||||||
|
unlink("log.txt");
|
||||||
|
}
|
||||||
|
|
||||||
|
$fp = fopen("log.txt", "w+");
|
||||||
|
fwrite($fp, "Started division operation \r\n");
|
||||||
|
|
||||||
|
$data = fopen($file, "r");
|
||||||
|
|
||||||
|
if(file_exists("result.csv")) {
|
||||||
|
unlink("result.csv");
|
||||||
|
}
|
||||||
|
|
||||||
|
while (($line = fgets($data)) !== false) {
|
||||||
|
$line = explode(";", $line);
|
||||||
|
$line[0] = intval($line[0]);
|
||||||
|
$line[1] = intval($line[1]);
|
||||||
|
if($line[1] === 0) {
|
||||||
|
fwrite($fp, "numbers ".$line[0] . " and ". $line[1]." are wrong \r\n");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
$result = $line[0] / $line[1];
|
||||||
|
if($result < 0) {
|
||||||
|
fwrite($fp, "numbers ".$line[0] . " and ". $line[1]." are wrong \r\n");
|
||||||
|
} else {
|
||||||
|
$resultHandle = fopen("result.csv", "a+");
|
||||||
|
$result = $line[0].";".$line[1].";".$result."\r\n";
|
||||||
|
fwrite($resultHandle, $result);
|
||||||
|
fclose($resultHandle);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fwrite($fp, "Finished division operation \r\n");
|
||||||
|
fclose($fp);
|
||||||
|
fclose($data);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue