Skip to content

Commit 2a9890c

Browse files
author
jessevz
committed
Added helper endpoint to generate image of the progress of a task
1 parent 47045bd commit 2a9890c

File tree

1 file changed

+221
-0
lines changed

1 file changed

+221
-0
lines changed
Lines changed: 221 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,221 @@
1+
<?php
2+
3+
use DBA\Chunk;
4+
use JetBrains\PhpStorm\NoReturn;
5+
use Psr\Http\Message\ResponseInterface as Response;
6+
use Psr\Http\Message\ServerRequestInterface as Request;
7+
use DBA\Factory;
8+
use DBA\OrderFilter;
9+
use DBA\QueryFilter;
10+
use DBA\Task;
11+
use Middlewares\Utils\HttpErrorException;
12+
use Slim\Exception\HttpNotFoundException;
13+
14+
require_once(dirname(__FILE__) . "/../common/AbstractHelperAPI.class.php");
15+
16+
class GetTaskProgressImageHelperAPI extends AbstractHelperAPI {
17+
public static function getBaseUri(): string {
18+
return "/api/v2/helper/getTaskProgressImage";
19+
}
20+
21+
public static function getAvailableMethods(): array {
22+
return ['GET'];
23+
}
24+
25+
public function getRequiredPermissions(string $method): array {
26+
return [Task::PERM_READ];
27+
}
28+
29+
/**
30+
* getfile is different because it returns actual binary data.
31+
*/
32+
public static function getResponse(): null {
33+
return null;
34+
}
35+
36+
37+
#[NoReturn] public function actionPost(array $data): object|array|null {
38+
assert(False, "GetTaskProgressImage has no POST");
39+
}
40+
41+
/**
42+
* Description of get params for swagger.
43+
*/
44+
public function getParamsSwagger(): array {
45+
return [
46+
[
47+
"in" => "query",
48+
"name" => "supertask",
49+
"schema" => [
50+
"type" => "integer",
51+
"format" => "int32"
52+
],
53+
"required" => true,
54+
"example" => 1,
55+
"description" => "The ID of the supertask where you want to create the progress image of."
56+
],
57+
[
58+
"in" => "query",
59+
"name" => "task",
60+
"schema" => [
61+
"type" => "integer",
62+
"format" => "int32"
63+
],
64+
"required" => true,
65+
"example" => 1,
66+
"description" => "The ID of the task where you want to create the progress image of."
67+
]
68+
];
69+
}
70+
71+
/**
72+
* Endpoint to download files
73+
* @param Request $request
74+
* @param Response $response
75+
* @return Response
76+
* @throws HTException
77+
* @throws HttpErrorException
78+
* @throws HttpForbidden
79+
*/
80+
public function handleGet(Request $request, Response $response): Response {
81+
$this->preCommon($request);
82+
$task_id = $request->getQueryParams()['task'];
83+
$supertask_id = $request->getQueryParams()['supertask'];
84+
85+
//check if task exists and get information
86+
if ($task_id) {
87+
$task = Factory::getTaskFactory()->get($task_id);
88+
if ($task == null) {
89+
throw new HttpNotFoundException($request, "Invalid file");
90+
}
91+
$taskWrapper = Factory::getTaskWrapperFactory()->get($task->getTaskWrapperId());
92+
if ($taskWrapper == null) {
93+
throw new HttpError("Inconsistency on task!");
94+
}
95+
}
96+
else if ($supertask_id) {
97+
$taskWrapper = Factory::getTaskWrapperFactory()->get($_GET['supertask']);
98+
if ($taskWrapper == null) {
99+
throw new HttpError("Invalid task wrapper!");
100+
}
101+
} else {
102+
throw new HttpError("No task or super task has been provided");
103+
}
104+
105+
$size = array(1500, 32);
106+
107+
//create image
108+
$image = imagecreatetruecolor($size[0], $size[1]);
109+
imagesavealpha($image, true);
110+
111+
//set colors
112+
$transparency = imagecolorallocatealpha($image, 0, 0, 0, 127);
113+
$yellow = imagecolorallocate($image, 255, 255, 0);
114+
$red = imagecolorallocate($image, 255, 0, 0);
115+
$grey = imagecolorallocate($image, 192, 192, 192);
116+
$green = imagecolorallocate($image, 0, 255, 0);
117+
$blue = imagecolorallocate($image, 60, 60, 245);
118+
119+
//prepare image
120+
imagefill($image, 0, 0, $transparency);
121+
122+
if ($taskWrapper->getTaskType() == DTaskTypes::SUPERTASK && isset($supertask_id)) {
123+
// handle supertask progress drawing here
124+
$qF = new QueryFilter(Task::TASK_WRAPPER_ID, $taskWrapper->getId(), "=");
125+
$oF = new OrderFilter(Task::PRIORITY, "DESC");
126+
$tasks = Factory::getTaskFactory()->filter([Factory::FILTER => $qF, Factory::ORDER => $oF]);
127+
$numTasks = sizeof($tasks);
128+
for ($i = 0; $i < sizeof($tasks); $i++) {
129+
$qF = new QueryFilter(Chunk::TASK_ID, $tasks[$i]->getId(), "=");
130+
$chunks = Factory::getChunkFactory()->filter([Factory::FILTER => $qF]);
131+
$progress = 0;
132+
foreach ($chunks as $chunk) {
133+
$progress += $chunk->getCheckpoint();
134+
}
135+
$qF = new QueryFilter(Chunk::TASK_ID, $tasks[$i]->getId(), "=");
136+
$chunks = Factory::getChunkFactory()->filter([Factory::FILTER => $qF]);
137+
$cracked = 0;
138+
foreach ($chunks as $chunk) {
139+
$cracked += $chunk->getCracked();
140+
}
141+
if ($cracked > 0) {
142+
imagefilledrectangle($image, $i * $size[0] / $numTasks, 0, ($i + 1) * $size[0] / $numTasks, $size[1] - 1, $green);
143+
}
144+
else if ($tasks[$i]->getKeyspace() > 0 && $progress >= $tasks[$i]->getKeyspace()) {
145+
imagefilledrectangle($image, $i * $size[0] / $numTasks, 0, ($i + 1) * $size[0] / $numTasks, $size[1] - 1, $blue);
146+
}
147+
else if ($tasks[$i]->getKeyspace() > 0 && $progress > 0) {
148+
imagefilledrectangle($image, $i * $size[0] / $numTasks, 0, ($i + 1) * $size[0] / $numTasks, $size[1] - 1, $yellow);
149+
}
150+
else {
151+
imagefilledrectangle($image, $i * $size[0] / $numTasks, 0, ($i + 1) * $size[0] / $numTasks, $size[1] - 1, $grey);
152+
}
153+
}
154+
}
155+
else {
156+
$progress = $task->getKeyspaceProgress();
157+
$keyspace = max($task->getKeyspace(), 1);
158+
159+
//load chunks
160+
$qF = new QueryFilter(Task::TASK_ID, $task->getId(), "=");
161+
$chunks = Factory::getChunkFactory()->filter([Factory::FILTER => $qF]);
162+
foreach ($chunks as $chunk) {
163+
if ($task->getUsePreprocessor() == 1 && $task->getKeyspace() <= 0) {
164+
continue;
165+
}
166+
$start = floor(($size[0] - 1) * $chunk->getSkip() / $keyspace);
167+
$end = floor(($size[0] - 1) * ($chunk->getSkip() + $chunk->getLength()) / $keyspace) - 1;
168+
//division by 10000 is required because rprogress is saved in percents with two decimals
169+
$current = floor(($size[0] - 1) * ($chunk->getSkip() + $chunk->getLength() * $chunk->getProgress() / 10000) / $keyspace) - 1;
170+
171+
if ($current > $end) {
172+
$current = $end;
173+
}
174+
175+
if ($end - $start < 3) {
176+
if ($chunk->getState() >= 6) {
177+
imagefilledrectangle($image, $start, 0, $end, $size[1] - 1, $red);
178+
}
179+
else if ($chunk->getCracked() > 0) {
180+
imagefilledrectangle($image, $start, 0, $end, $size[1] - 1, $green);
181+
}
182+
else {
183+
imagefilledrectangle($image, $start, 0, $end, $size[1] - 1, $yellow);
184+
}
185+
}
186+
else {
187+
if ($chunk->getState() >= 6) {
188+
imagerectangle($image, $start, 0, $end, ($size[1] - 1), $red);
189+
}
190+
else {
191+
imagerectangle($image, $start, 0, $end, ($size[1] - 1), $grey);
192+
}
193+
if ($chunk->getCracked() > 0) {
194+
imagefilledrectangle($image, $start + 1, 1, $current - 1, $size[1] - 2, $green);
195+
}
196+
else {
197+
imagefilledrectangle($image, $start + 1, 1, $current - 1, $size[1] - 2, $yellow);
198+
}
199+
}
200+
}
201+
}
202+
203+
//send image data to output
204+
imagepng($image);
205+
return $response->withStatus(200)
206+
->withHeader("Content-Type", "image/png")
207+
->withHeader("Cache-Control", "no-cache");
208+
}
209+
210+
static public function register($app): void {
211+
$baseUri = GetTaskProgressImageHelperAPI::getBaseUri();
212+
213+
/* Allow CORS preflight requests */
214+
$app->options($baseUri, function (Request $request, Response $response): Response {
215+
return $response;
216+
});
217+
$app->get($baseUri, "GetTaskProgressImageHelperAPI:handleGet");
218+
}
219+
}
220+
221+
GetTaskProgressImageHelperAPI::register($app);

0 commit comments

Comments
 (0)