2025-10-11 13:38:30 +00:00
|
|
|
<?php
|
|
|
|
|
|
2026-04-08 07:22:13 +00:00
|
|
|
use App\Models\Tasks;
|
|
|
|
|
use GuzzleHttp\Client;
|
2025-10-11 13:38:30 +00:00
|
|
|
use Illuminate\Support\Facades\Route;
|
|
|
|
|
use Illuminate\Http\Request;
|
|
|
|
|
use Illuminate\Support\Facades\Response;
|
|
|
|
|
use Illuminate\Support\Facades\DB;
|
|
|
|
|
use App\Models\Attendance;
|
|
|
|
|
use App\Models\ai;
|
|
|
|
|
use App\Models\User;
|
|
|
|
|
use Illuminate\Support\Facades\Http;
|
|
|
|
|
use \Carbon\Carbon;
|
|
|
|
|
use Morilog\Jalali\Jalalian;
|
2026-04-08 07:22:13 +00:00
|
|
|
use App\Models\Pivot_Tasks;
|
|
|
|
|
use App\Http\Controllers\TaskController;
|
|
|
|
|
use App\Http\Controllers\FingerprintController;
|
|
|
|
|
|
2025-10-11 13:38:30 +00:00
|
|
|
|
|
|
|
|
use function PHPUnit\Framework\returnSelf;
|
|
|
|
|
|
|
|
|
|
Route::get('/', function () {
|
|
|
|
|
return view('attendance.index');
|
|
|
|
|
return view('welcome');
|
|
|
|
|
});
|
2026-04-08 07:22:13 +00:00
|
|
|
|
2026-04-08 09:22:17 +00:00
|
|
|
Route::post('/login', [\App\Http\Controllers\AttendanceController::class, 'login1']);
|
|
|
|
|
|
2026-04-08 07:22:13 +00:00
|
|
|
Route::post('/task/create', [TaskController::class, 'addTask'])->name('createTask');
|
|
|
|
|
|
2025-10-11 13:38:30 +00:00
|
|
|
Route::get('/ai', function () {
|
|
|
|
|
|
|
|
|
|
$response = Http::withHeaders([
|
|
|
|
|
'Authorization' => 'Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6IjA2OWZlZGJiLTk2ZDctNGU4MC1iMDA0LWFmZDZjMmU4YmZkZiIsImxhc3RfcGFzc3dvcmRfY2hhbmdlIjoxNzUwNjYwODczLCJleHAiOjE3NTQ3NTcxMDR9.qAQF8XDOU8NRz5vSiFlQfnrj8dhGhJ5uvJqjblQWmr8',
|
|
|
|
|
'Cookie' => 'x-ap=eu-central-1; acw_tc=0a03e56c17521661095906021e3cacb270c127c80eb3a20489a465ab4beae1',
|
|
|
|
|
])->post('https://chat.qwen.ai/api/v2/chat/completions?chat_id=7ce2a60a-2b40-4ae8-8536-0cd346642de3', [
|
|
|
|
|
'stream' => false,
|
|
|
|
|
'incremental_output' => true,
|
|
|
|
|
'chat_id' => '7ce2a60a-2b40-4ae8-8536-0cd346642de3',
|
|
|
|
|
'chat_mode' => 'normal',
|
|
|
|
|
'model' => 'qwen3-235b-a22b',
|
|
|
|
|
'messages' => [
|
|
|
|
|
[
|
|
|
|
|
'role' => 'user',
|
|
|
|
|
'content' => 'یه جمله انگیزشی بده که خاص، کوبنده و غیرکلیشهای باشه. نه مثل بقیه.',
|
|
|
|
|
'user_action' => 'chat',
|
|
|
|
|
'files' => [],
|
|
|
|
|
'timestamp' => 1752165316,
|
|
|
|
|
'models' => ['qwen3-235b-a22b'],
|
|
|
|
|
'chat_type' => 't2t',
|
|
|
|
|
'feature_config' => [
|
|
|
|
|
'thinking_enabled' => false,
|
|
|
|
|
'output_schema' => 'phase'
|
|
|
|
|
],
|
|
|
|
|
'extra' => [
|
|
|
|
|
'meta' => [
|
|
|
|
|
'subChatType' => 't2t'
|
|
|
|
|
]
|
|
|
|
|
],
|
|
|
|
|
'sub_chat_type' => 't2t',
|
|
|
|
|
'parent_id' => 'df0a0c91-53d5-4a04-b5da-b8ac53d6d821'
|
|
|
|
|
]
|
|
|
|
|
],
|
|
|
|
|
'timestamp' => 1752165316
|
|
|
|
|
]);
|
|
|
|
|
// Get the response
|
|
|
|
|
$responseData = $response->json();
|
|
|
|
|
$content = $responseData['data']['choices'][0]['message']['content'];
|
|
|
|
|
$ai = new ai(); // Or use your correct namespace
|
|
|
|
|
$ai->key = 'angizeh'; // Assuming you fixed 'kay' to 'key' in migration
|
|
|
|
|
$ai->prompt = 'فقط یک جمله کوتاه انگیزشی بگو';
|
|
|
|
|
$ai->response = $content;
|
|
|
|
|
$ai->save();
|
|
|
|
|
|
|
|
|
|
dd($ai);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
Route::post('attendance/enter', function (Request $request) {
|
|
|
|
|
// return $request;
|
|
|
|
|
// 32.6504751, 51.6936045
|
|
|
|
|
$user_identity = $request->input('name');
|
|
|
|
|
setcookie('user_identity', $user_identity, time() + (60 * 60 * 24 * 365 * 5), "/");
|
|
|
|
|
$userLat = $request->input('latitude');
|
|
|
|
|
$userLng = $request->input('longitude');
|
|
|
|
|
$officeLat = 32.6504751;
|
|
|
|
|
$officeLng = 51.6936045;
|
|
|
|
|
|
|
|
|
|
if (!$userLat || !$userLng) {
|
|
|
|
|
return response()->json(['error' => 'مختصات دریافت نشد.'], 422);
|
|
|
|
|
}
|
|
|
|
|
$attendance = Attendance::where('user_identity', $user_identity)
|
|
|
|
|
->whereNull('exited_at')
|
|
|
|
|
->latest('entered_at')
|
|
|
|
|
->first();
|
|
|
|
|
if ($attendance) {
|
|
|
|
|
$attendance->exited_at = now();
|
|
|
|
|
$attendance->exit_location = ['lat' => $userLat, 'lng' => $userLng];
|
|
|
|
|
$attendance->ip_exit = $userLng;
|
|
|
|
|
$attendance->distance_exit = $request->input('distance');
|
|
|
|
|
$attendance->save();
|
|
|
|
|
return redirect()->back()->with('message', [
|
|
|
|
|
'color' => '#3b82f6',
|
|
|
|
|
'text' => 'خروج با موفقیت ثبت شد.',
|
|
|
|
|
]);
|
|
|
|
|
} else {
|
|
|
|
|
$attendance = new Attendance();
|
|
|
|
|
$attendance->user_id = 0;
|
|
|
|
|
$attendance->user_identity = $user_identity ?? '';
|
|
|
|
|
$attendance->distance = $request->input('distance');
|
|
|
|
|
$attendance->ip_address = $request->ip();
|
|
|
|
|
$attendance->entered_at = now();
|
|
|
|
|
$attendance->entry_location = ['lat' => $userLat, 'lng' => $userLng];
|
|
|
|
|
$attendance->office_location = ['lat' => $officeLat, 'lng' => $officeLng];
|
|
|
|
|
$attendance->save();
|
|
|
|
|
|
|
|
|
|
return redirect()->back()->with('message', [
|
|
|
|
|
'color' => '#22c55e',
|
|
|
|
|
'text' => 'ورود با موفقیت ثبت شد.',
|
|
|
|
|
]);
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
2026-04-27 16:48:01 +00:00
|
|
|
Route::post('/1', function (Request $request) {
|
|
|
|
|
$data = $request->all();
|
2026-05-03 13:29:25 +00:00
|
|
|
if(isset($data['callback_query']))
|
|
|
|
|
unset($data['callback_query']['message']['text']);
|
2026-04-27 16:48:01 +00:00
|
|
|
try{
|
2026-05-03 13:29:25 +00:00
|
|
|
Http::withoutVerifying()->timeout(3)->retry(3, 2000)->post('https://tapi.bale.ai/1590900041:Bguk5alo4fv83JmN4kdkOTZ1A4mnvASqVwE/sendMessage', [
|
2026-04-27 16:48:01 +00:00
|
|
|
"chat_id"=> "985309723",
|
|
|
|
|
"text"=> json_encode($data, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT),
|
|
|
|
|
]);
|
2026-05-03 13:29:25 +00:00
|
|
|
}catch(\Exception $e){
|
|
|
|
|
Http::withoutVerifying()->timeout(3)->post('https://tapi.bale.ai/1590900041:Bguk5alo4fv83JmN4kdkOTZ1A4mnvASqVwE/sendMessage', [
|
|
|
|
|
"chat_id"=> "985309723",
|
|
|
|
|
"text"=> json_encode($e->getMessage(), JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT),
|
|
|
|
|
]);
|
|
|
|
|
}
|
2026-04-27 16:48:01 +00:00
|
|
|
return true;
|
|
|
|
|
});
|
|
|
|
|
|
2025-10-11 13:38:30 +00:00
|
|
|
Route::post('/pplain', function (Request $request) {
|
|
|
|
|
//functions
|
|
|
|
|
function savedb($d)
|
|
|
|
|
{
|
|
|
|
|
DB::table('tst')->insert([
|
|
|
|
|
'data' => json_encode($d),
|
|
|
|
|
]);
|
|
|
|
|
}
|
2026-04-08 07:22:13 +00:00
|
|
|
|
2025-10-11 13:38:30 +00:00
|
|
|
function sendbot($chatid, $mssg)
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
// ارسال به پیوی تلگرام
|
|
|
|
|
$sent = Http::get("https://api.wwwapp.ir/telegran_send.php", [
|
|
|
|
|
'botToken' => "7467099619:AAF2V6yYcbAb8oSIRSCyH5i2GKfdWVO3a7k",
|
|
|
|
|
'chatId' => $chatid,
|
|
|
|
|
'message' => $mssg,
|
|
|
|
|
'parse_mode' => 'Markdown'
|
|
|
|
|
]);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$data = $request->all();
|
|
|
|
|
savedb($data);
|
2026-04-08 07:22:13 +00:00
|
|
|
|
|
|
|
|
// sendbot('115247194', 'before update');
|
|
|
|
|
try {
|
|
|
|
|
|
|
|
|
|
update_tasks($data);
|
|
|
|
|
}catch (\Exception $e){
|
|
|
|
|
sendbot('115247194', $e->getMessage());
|
|
|
|
|
}
|
|
|
|
|
// sendbot('115247194', 'after update');
|
|
|
|
|
|
2025-10-11 13:38:30 +00:00
|
|
|
$message = "";
|
|
|
|
|
$aclist = [
|
|
|
|
|
'updated' => '🔄',
|
|
|
|
|
'created' => '🆕',
|
|
|
|
|
// 'urgent'=>'🟥',
|
|
|
|
|
// 'high'=>'🟧',
|
|
|
|
|
// 'medium'=>'🟨',
|
|
|
|
|
// 'low'=>'🟩',
|
|
|
|
|
// 'none'=>'⚪'
|
|
|
|
|
];
|
|
|
|
|
//create message
|
|
|
|
|
if ($data['event'] == 'project') {
|
|
|
|
|
$prjlead = $data['data']['project_lead'] ?? "";
|
|
|
|
|
$action = $data['action'] ?? "";
|
|
|
|
|
if ($prjlead != "" && $action != "") {
|
|
|
|
|
$desc = "\nتوضیحات:\nعملیات ({$action}) توسط کاربر ({$prjlead}) انجام شده است.";
|
|
|
|
|
}
|
|
|
|
|
|
2026-04-08 07:22:13 +00:00
|
|
|
!empty($data['action']) && $message .= "{$aclist[$data['action']]}\n";
|
|
|
|
|
!empty($data['data']['name']) && $message .= "{$data['data']['name']} ";
|
2025-10-11 13:38:30 +00:00
|
|
|
if (!$data['data']['priority'] == 'none')
|
2026-04-08 07:22:13 +00:00
|
|
|
!empty($data['data']['priority']) && $message .= "({$data['data']['priority']})";
|
2025-10-11 13:38:30 +00:00
|
|
|
!empty($desc) && $message .= $desc;
|
2026-04-08 07:22:13 +00:00
|
|
|
!empty($data['data']['updated_at']) && $message .= "\n" . Jalalian::fromCarbon(Carbon::parse($data['data']['updated_at']))->format('Y/m/d')
|
2025-10-11 13:38:30 +00:00
|
|
|
. "\n";
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
!empty($data['description_text']) && $message .= "\n{$data['description_text']}";
|
|
|
|
|
} elseif ($data['event'] == 'issue') {
|
|
|
|
|
|
|
|
|
|
if (isset($data['activity'])) {
|
|
|
|
|
|
|
|
|
|
$field = $data['activity']['field'] ?? "نامشخص";
|
|
|
|
|
$actor = $data['activity']['actor']['last_name'] ?? "نامشخص";
|
|
|
|
|
$oldvalue = $data['activity']['old_value'] ?? "نامشخص";
|
|
|
|
|
$newvalue = $data['activity']['new_value'] ?? "نامشخص";
|
2026-04-08 07:22:13 +00:00
|
|
|
if (($field == 'start_date' || $field == 'target_date') && $field != 'نامشخص') {
|
|
|
|
|
if (strtotime($field) != 'false') {
|
2025-10-11 13:38:30 +00:00
|
|
|
$oldvalue = Jalalian::fromCarbon(Carbon::parse($oldvalue))->format('Y/m/d');
|
|
|
|
|
$newvalue = Jalalian::fromCarbon(Carbon::parse($newvalue))->format('Y/m/d');
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if ($field == 'sort_order' || $field == 'state_id') {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
$desc = "کاربر ({$actor}) مقدار ({$field}) را از ({$oldvalue}) به ({$newvalue}) تغییر داد.";
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
|
|
$desc = "وظیفه در سایت چک شود.";
|
|
|
|
|
}
|
|
|
|
|
!empty($data['data']['start_date']) && $startdate = Jalalian::fromCarbon(Carbon::parse($data['data']['start_date']))->format('Y/m/d');
|
|
|
|
|
!empty($data['data']['target_date']) && $enddate = Jalalian::fromCarbon(Carbon::parse($data['data']['target_date']))->format('Y/m/d');
|
|
|
|
|
|
2026-04-08 07:22:13 +00:00
|
|
|
!empty($data['action']) && $message .= "{$aclist[$data['action']]}";
|
|
|
|
|
!empty($data['data']['name']) && $message .= "{$data['data']['name']} ";
|
2025-10-11 13:38:30 +00:00
|
|
|
if ($data['data']['priority'] != "none") {
|
|
|
|
|
$message .= "({$data['data']['priority']})";
|
|
|
|
|
}
|
|
|
|
|
$message .= "\n" . $desc;
|
2026-04-08 07:22:13 +00:00
|
|
|
!empty($data['data']['assignees']) && $message .= "\n" . implode(', ', array_column($data['data']['assignees'], 'last_name')) . "\n";
|
2025-10-11 13:38:30 +00:00
|
|
|
|
|
|
|
|
if (!empty($startdate) && !empty($enddate)) {
|
|
|
|
|
$message .= "{$startdate} ➡️ {$enddate}";
|
|
|
|
|
} elseif (!empty($startdate)) {
|
|
|
|
|
$message .= "تاریخ شروع مهلت پروژه: {$startdate}";
|
|
|
|
|
} elseif (!empty($enddate)) {
|
|
|
|
|
$message .= "تاریخ اتمام مهلت پروژه: {$enddate}";
|
|
|
|
|
}
|
|
|
|
|
// !empty($data['data']['target_date']) && $message .= "تاریخ اتمام مهلت پروژه: ".Jalalian::fromCarbon(Carbon::parse($data['data']['target_date']))->format('Y/m/d') ."\n";
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
$assignees = array_column($data['data']['assignees'], 'email');
|
|
|
|
|
$members = User::select('email', 'chatid')->get();
|
|
|
|
|
$gpid = -4742642674;
|
|
|
|
|
if (empty($assignees)) {
|
|
|
|
|
|
|
|
|
|
sendbot($gpid, $message);
|
|
|
|
|
} else {
|
|
|
|
|
sendbot($gpid, $message);
|
|
|
|
|
foreach ($assignees as $item) {
|
|
|
|
|
foreach ($members as $member) {
|
|
|
|
|
if ($member->email == $item) {
|
|
|
|
|
//sent message
|
|
|
|
|
sendbot($member->chatid, $message);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return response()->json(['status' => 'ok'], 200);
|
|
|
|
|
});
|
2026-04-08 07:22:13 +00:00
|
|
|
|
|
|
|
|
Route::post('/fingerprint/register/options', [FingerprintController::class, 'generateRegisterOptions'])->name('fingerprint.register.options');
|
|
|
|
|
|
|
|
|
|
Route::post('/fingerprint/register/verify', [FingerprintController::class, 'verifyRegister'])->name('fingerprint.register.verify');
|
|
|
|
|
|
|
|
|
|
function update_tasks($req)
|
|
|
|
|
{
|
|
|
|
|
if ($req['action'] == "deleted") {
|
|
|
|
|
Pivot_Tasks::where('task_id', $req['data']['task_id'])->delete();
|
|
|
|
|
Tasks::where('task_id', $req['data']['task_id'])->delete();
|
|
|
|
|
return "deleted";
|
|
|
|
|
} else {
|
|
|
|
|
$req = $req['data'];
|
|
|
|
|
|
|
|
|
|
$project_id = $req['project'];
|
|
|
|
|
$task_id = $req['id'];
|
|
|
|
|
$users = User::all();
|
|
|
|
|
$task = Tasks::where('task_id', $task_id)->first();
|
|
|
|
|
|
|
|
|
|
$client = new Client();
|
|
|
|
|
|
|
|
|
|
$response = $client->get("https://api.plane.so/api/v1/workspaces/montzar/projects/$project_id/issues/$task_id", [
|
|
|
|
|
'headers' => [
|
|
|
|
|
'X-API-Key' => 'plane_api_ec378e977ceb4bd1bbd2332855370645',
|
|
|
|
|
'Accept' => 'application/json'
|
|
|
|
|
]
|
|
|
|
|
]);
|
|
|
|
|
|
|
|
|
|
$data = json_decode($response->getBody(), true);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// $client = new Client();
|
|
|
|
|
//
|
|
|
|
|
// $res = $client->get("https://api.plane.so/api/workspaces/montzar/projects/$project_id/modules/", [
|
|
|
|
|
// 'headers' => [
|
|
|
|
|
// 'cookie' => 'session-id=vmc3jbuj391b5reqguhufrf7220dcu8pwceloulwisr1pxfqxbe7k2low9x7647sykt4onlwqdxci0holvqc023lvjac4xgwtst5umzxkl0mfu68xg2b2e3821f59797; '
|
|
|
|
|
// ]
|
|
|
|
|
// ]);
|
|
|
|
|
// $res = json_decode($res->getBody(), true);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if ($task) {
|
|
|
|
|
try {
|
|
|
|
|
$task->task_id = $data['id'];
|
|
|
|
|
$task->name = $data['name'];
|
|
|
|
|
$task->description = $data['description'] ?? null;
|
|
|
|
|
$task->workspace_slug = "montzar";
|
|
|
|
|
$task->assignees = json_encode($data['assignees']) ?? null;
|
|
|
|
|
$task->start_date = $data['start_date'] ?? null;
|
|
|
|
|
$task->target_date = $data['target_date'] ?? null;
|
|
|
|
|
$task->priority = $data['priority'];
|
|
|
|
|
$task->description_html = $data['description_html'] ?? null;
|
|
|
|
|
$task->completed_at = $data['completed_at'] ?? null;
|
|
|
|
|
$task->project = $data['project'];
|
|
|
|
|
$task->workspace = $data['workspace'];
|
|
|
|
|
$task->state = $data['state'] ?? null;
|
|
|
|
|
$task->json = json_encode($data);
|
|
|
|
|
$task->created_at = $data['created_at'];
|
|
|
|
|
$task->updated_at = $data['updated_at'];
|
|
|
|
|
$task->deleted_at = $data['deleted_at'] ?? null;
|
|
|
|
|
$task->created_by = $data['created_by'];
|
|
|
|
|
$task->updated_by = $data['updated_by'];
|
|
|
|
|
$task->deleted_by = $data['deleted_by'] ?? null;
|
|
|
|
|
$task->parent = $data['parent'] ?? null;
|
|
|
|
|
$task->task_type = !empty($data['parent']) ? 'sub_work_item' : 'work_item';
|
|
|
|
|
$task->save();
|
|
|
|
|
} catch (\Exception $e) {
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
try {
|
|
|
|
|
$task = new Tasks();
|
|
|
|
|
$task->task_id = $data['id'];
|
|
|
|
|
$task->name = $data['name'];
|
|
|
|
|
$task->description = $data['description'] ?? null;
|
|
|
|
|
$task->workspace_slug = "montzar";
|
|
|
|
|
$task->assignees = json_encode($data['assignees']) ?? null;
|
|
|
|
|
$task->start_date = $data['start_date'] ?? null;
|
|
|
|
|
$task->target_date = $data['target_date'] ?? null;
|
|
|
|
|
$task->priority = $data['priority'];
|
|
|
|
|
$task->description_html = $data['description_html'] ?? null;
|
|
|
|
|
$task->completed_at = $data['completed_at'] ?? null;
|
|
|
|
|
$task->project = $data['project'];
|
|
|
|
|
$task->workspace = $data['workspace'];
|
|
|
|
|
$task->state = $data['state'] ?? null;
|
|
|
|
|
$task->json = json_encode($data);
|
|
|
|
|
$task->created_at = $data['created_at'];
|
|
|
|
|
$task->updated_at = $data['updated_at'];
|
|
|
|
|
$task->deleted_at = $data['deleted_at'] ?? null;
|
|
|
|
|
$task->created_by = $data['created_by'];
|
|
|
|
|
$task->updated_by = $data['updated_by'];
|
|
|
|
|
$task->deleted_by = $data['deleted_by'] ?? null;
|
|
|
|
|
$task->parent = $data['parent'] ?? null;
|
|
|
|
|
$task->save();
|
|
|
|
|
} catch (\Exception $e) {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
$assigns = $data['assignees'];
|
|
|
|
|
$created_by = $data['created_by'];
|
|
|
|
|
if (!empty($assigns)) {
|
|
|
|
|
|
|
|
|
|
foreach ($users as $user) {
|
|
|
|
|
if (in_array($user->plain_id, $assigns)) {
|
|
|
|
|
Pivot_Tasks::insert([
|
|
|
|
|
'task_id' => $data['id'], // یا $task->task_id اگر این همون PK هست
|
|
|
|
|
'user_id' => $user->plain_id
|
|
|
|
|
]);
|
|
|
|
|
}
|
|
|
|
|
if (($user->plain_id == $created_by)) {
|
|
|
|
|
Pivot_Tasks::insertOrIgnore([
|
|
|
|
|
'task_id' => $data['id'], // یا $task->task_id اگر این همون PK هست
|
|
|
|
|
'user_id' => $user->plain_id
|
|
|
|
|
]);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|