complete absensi page with absensi json, and created a new page so boss can see attendance
This commit is contained in:
parent
170b46e718
commit
13cbb8ce02
|
@ -0,0 +1 @@
|
||||||
|
[]
|
|
@ -1 +1 @@
|
||||||
[{"name": "Naufal", "nik": "1"}]
|
[{"name": "Naufal", "nik": "1"}, {"name": "Aran", "nik": "12345"}]
|
||||||
|
|
52
flask_app.py
52
flask_app.py
|
@ -2,8 +2,10 @@ from flask import Flask, render_template , request
|
||||||
import subprocess
|
import subprocess
|
||||||
import threading
|
import threading
|
||||||
import json
|
import json
|
||||||
|
import time
|
||||||
|
|
||||||
dataset = "dataset.json"
|
dataset = "dataset.json"
|
||||||
|
absensi = "absensi.json"
|
||||||
|
|
||||||
app = Flask(__name__, static_folder='assets', template_folder='templates')
|
app = Flask(__name__, static_folder='assets', template_folder='templates')
|
||||||
|
|
||||||
|
@ -34,7 +36,55 @@ def run_main2_py():
|
||||||
|
|
||||||
@app.route('/')
|
@app.route('/')
|
||||||
def home():
|
def home():
|
||||||
return render_template('index.html')
|
today_date = time.strftime("%d/%m/%Y")
|
||||||
|
all_data = None
|
||||||
|
len_all_data = 0
|
||||||
|
# open absensi file
|
||||||
|
with open(absensi, 'r') as f:
|
||||||
|
data = json.load(f)
|
||||||
|
len_data = len(data)
|
||||||
|
|
||||||
|
# if data is not empty
|
||||||
|
if len_data > 0:
|
||||||
|
# get the last data
|
||||||
|
last_data = data[len_data - 1]
|
||||||
|
# check if "date" is today
|
||||||
|
if last_data['date'] == today_date:
|
||||||
|
# get all the "absensi" data
|
||||||
|
all_data = last_data['absensi']
|
||||||
|
# get the length of the "absensi" data
|
||||||
|
len_all_data = len(all_data)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
return render_template('index.html', data=all_data, length=len_all_data, today_date=today_date)
|
||||||
|
|
||||||
|
@app.route('/cek_absensi')
|
||||||
|
def cek_absensi():
|
||||||
|
today_date = time.strftime("%d/%m/%Y")
|
||||||
|
all_data = None
|
||||||
|
len_all_data = 0
|
||||||
|
# open absensi file
|
||||||
|
with open(absensi, 'r') as f:
|
||||||
|
data = json.load(f)
|
||||||
|
len_data = len(data)
|
||||||
|
|
||||||
|
# if data is not empty
|
||||||
|
if len_data > 0:
|
||||||
|
# get the last data
|
||||||
|
last_data = data[len_data - 1]
|
||||||
|
# check if "date" is today
|
||||||
|
if last_data['date'] == today_date:
|
||||||
|
# get all the "absensi" data
|
||||||
|
all_data = last_data['absensi']
|
||||||
|
# get the length of the "absensi" data
|
||||||
|
len_all_data = len(all_data)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
return render_template('index2.html', data=all_data, length=len_all_data, today_date=today_date)
|
||||||
|
|
||||||
@app.route('/scan_face')
|
@app.route('/scan_face')
|
||||||
def scan_face():
|
def scan_face():
|
||||||
|
|
124
main.py
124
main.py
|
@ -5,6 +5,16 @@ import numpy as np
|
||||||
import math
|
import math
|
||||||
import sys
|
import sys
|
||||||
import time
|
import time
|
||||||
|
import json
|
||||||
|
from datetime import datetime
|
||||||
|
|
||||||
|
absensi_file = "absensi.json"
|
||||||
|
|
||||||
|
today_date = time.strftime("%d/%m/%Y")
|
||||||
|
|
||||||
|
# open the dataset file
|
||||||
|
with open(absensi_file, 'r') as f:
|
||||||
|
data = json.load(f)
|
||||||
|
|
||||||
def face_confidence(face_distance, face_match_threshold=0.6):
|
def face_confidence(face_distance, face_match_threshold=0.6):
|
||||||
range = (1.0 - face_match_threshold)
|
range = (1.0 - face_match_threshold)
|
||||||
|
@ -49,7 +59,7 @@ class FaceRecognition:
|
||||||
sys.exit('Video capture is not opened')
|
sys.exit('Video capture is not opened')
|
||||||
|
|
||||||
no_face_timer = 0
|
no_face_timer = 0
|
||||||
no_face_threshold = 2 # Adjust this to your desired timeout in seconds
|
no_face_threshold = 5 # Adjust this to your desired timeout in seconds
|
||||||
|
|
||||||
while True:
|
while True:
|
||||||
ret, frame = video_capture.read()
|
ret, frame = video_capture.read()
|
||||||
|
@ -86,6 +96,118 @@ class FaceRecognition:
|
||||||
if float(confidence.split("%")[0]) > 55:
|
if float(confidence.split("%")[0]) > 55:
|
||||||
name = self.known_face_names[best_match_index]
|
name = self.known_face_names[best_match_index]
|
||||||
confidence = face_confidence(face_distances[best_match_index])
|
confidence = face_confidence(face_distances[best_match_index])
|
||||||
|
|
||||||
|
|
||||||
|
time_now = time.strftime("%H:%M:%S")
|
||||||
|
current_time = datetime.strptime(time.strftime("%H:%M:%S"), "%H:%M:%S")
|
||||||
|
|
||||||
|
print('this is the time now: ', time_now)
|
||||||
|
print('this is the current time: ', current_time)
|
||||||
|
|
||||||
|
compare_time = datetime.strptime("12:00:00", "%H:%M:%S")
|
||||||
|
|
||||||
|
print('this is the compare time: ', compare_time)
|
||||||
|
|
||||||
|
# check the last data to see if today's date is already there
|
||||||
|
if len(data) > 0:
|
||||||
|
last_data = data[-1]
|
||||||
|
else:
|
||||||
|
last_data = None
|
||||||
|
|
||||||
|
if last_data:
|
||||||
|
if last_data["date"] == today_date:
|
||||||
|
# loop through the "absensi" key to see if the name is already there
|
||||||
|
data_absensi = last_data["absensi"]
|
||||||
|
name_found = False
|
||||||
|
|
||||||
|
for absensi in data_absensi:
|
||||||
|
if absensi["name"] == name:
|
||||||
|
name_found = True
|
||||||
|
break
|
||||||
|
|
||||||
|
if not name_found:
|
||||||
|
# add new data
|
||||||
|
# if time_now > "12:00:00": then add the "jam_keluar" key
|
||||||
|
|
||||||
|
if current_time > compare_time:
|
||||||
|
data_absensi.append({
|
||||||
|
"name": name,
|
||||||
|
"jam_masuk": time_now,
|
||||||
|
"jam_keluar": time_now,
|
||||||
|
})
|
||||||
|
else:
|
||||||
|
data_absensi.append({
|
||||||
|
"name": name,
|
||||||
|
"jam_masuk": time_now,
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
# else update the data and change the "jam_keluar" key
|
||||||
|
else:
|
||||||
|
for absensi in data_absensi:
|
||||||
|
if absensi["name"] == name:
|
||||||
|
|
||||||
|
if current_time > compare_time:
|
||||||
|
absensi["jam_keluar"] = time_now
|
||||||
|
# else do nothing
|
||||||
|
else:
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
break
|
||||||
|
|
||||||
|
else:
|
||||||
|
# create new data
|
||||||
|
if current_time > compare_time:
|
||||||
|
data.append({
|
||||||
|
"date": today_date,
|
||||||
|
"absensi": [
|
||||||
|
{
|
||||||
|
"name": name,
|
||||||
|
"jam_masuk": time_now,
|
||||||
|
"jam_keluar": time_now,
|
||||||
|
}
|
||||||
|
]
|
||||||
|
})
|
||||||
|
else:
|
||||||
|
data.append({
|
||||||
|
"date": today_date,
|
||||||
|
"absensi": [
|
||||||
|
{
|
||||||
|
"name": name,
|
||||||
|
"jam_masuk": time_now,
|
||||||
|
}
|
||||||
|
]
|
||||||
|
})
|
||||||
|
else:
|
||||||
|
# create new data
|
||||||
|
if current_time > compare_time:
|
||||||
|
data.append({
|
||||||
|
"date": today_date,
|
||||||
|
"absensi": [
|
||||||
|
{
|
||||||
|
"name": name,
|
||||||
|
"jam_masuk": time_now,
|
||||||
|
"jam_keluar": time_now,
|
||||||
|
}
|
||||||
|
]
|
||||||
|
})
|
||||||
|
else:
|
||||||
|
data.append({
|
||||||
|
"date": today_date,
|
||||||
|
"absensi": [
|
||||||
|
{
|
||||||
|
"name": name,
|
||||||
|
"jam_masuk": time_now,
|
||||||
|
}
|
||||||
|
]
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
# write the data to the file
|
||||||
|
with open(absensi_file, 'w') as f:
|
||||||
|
json.dump(data, f, indent=4)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
name = "Unknown"
|
name = "Unknown"
|
||||||
confidence = 'Unknown'
|
confidence = 'Unknown'
|
||||||
|
|
|
@ -24,6 +24,8 @@
|
||||||
|
|
||||||
<!-- Color Picker -->
|
<!-- Color Picker -->
|
||||||
<link rel="stylesheet" href="assets/color-switcher/color-switcher.min.css">
|
<link rel="stylesheet" href="assets/color-switcher/color-switcher.min.css">
|
||||||
|
<link rel="stylesheet" href="assets/plugin/datatables/media/css/dataTables.bootstrap.min.css">
|
||||||
|
<link rel="stylesheet" href="assets/plugin/datatables/extensions/Responsive/css/responsive.bootstrap.min.css">
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
|
@ -51,15 +53,17 @@
|
||||||
<div class="main-content container">
|
<div class="main-content container">
|
||||||
<div class="row small-spacing">
|
<div class="row small-spacing">
|
||||||
<div class="col-lg-4 col-md-4 col-xs-6">
|
<div class="col-lg-4 col-md-4 col-xs-6">
|
||||||
<div class="box-content bg-success text-white" style="background :grey;cursor: pointer;" onclick="goto('home')">
|
<div class="box-content bg-success text-white" style="background :grey;cursor: pointer;"
|
||||||
|
onclick="goto('home')">
|
||||||
<h4 class="box-title">Halaman Utama</h4>
|
<h4 class="box-title">Halaman Utama</h4>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
<!-- /.box-content -->
|
<!-- /.box-content -->
|
||||||
</div>
|
</div>
|
||||||
<div class="col-lg-4 col-md-4 col-xs-6">
|
<div class="col-lg-4 col-md-4 col-xs-6">
|
||||||
<div class="box-content bg-info text-white" style="background :grey;cursor: pointer" onclick="goto('tambah_karyawan')"">
|
<div class="box-content bg-info text-white" style="background :grey;cursor: pointer"
|
||||||
<h4 class="box-title">Tambah Data Karyawan</h4>
|
onclick="goto('tambah_karyawan')"">
|
||||||
|
<h4 class=" box-title">Tambah Data Karyawan</h4>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
<!-- /.box-content -->
|
<!-- /.box-content -->
|
||||||
|
@ -67,7 +71,57 @@
|
||||||
</div>
|
</div>
|
||||||
<!-- create a button on center of this -->
|
<!-- create a button on center of this -->
|
||||||
<div class="row small-spacing text-center">
|
<div class="row small-spacing text-center">
|
||||||
<a href="{{url_for('scan_face')}}" class="btn btn-primary btn-bordered waves-effect waves-light">Lakukan Absensi</a>
|
<a href="{{url_for('scan_face')}}" class="btn btn-primary btn-bordered waves-effect waves-light">Lakukan
|
||||||
|
Absensi</a>
|
||||||
|
</div>
|
||||||
|
<br><br>
|
||||||
|
<div class="row small-spacing">
|
||||||
|
<div class="col-xs-2 col-md-2"></div>
|
||||||
|
<div class="col-xs-8 col-md-8">
|
||||||
|
<div class="box-content card">
|
||||||
|
<h4 class="box-title">Tanggal : {{today_date}}</h4>
|
||||||
|
<div class="card-content">
|
||||||
|
<table id="example" class="table table-striped table-bordered display" style="width:100%">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<td><b>Nama</b></td>
|
||||||
|
<td><b>Jam Masuk</b></td>
|
||||||
|
<td><b>Jam Keluar</b></td>
|
||||||
|
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{%if data %}
|
||||||
|
|
||||||
|
{% for i in range(0, length) %}
|
||||||
|
|
||||||
|
<tr>
|
||||||
|
<td>{{data[i]['name']}}</td>
|
||||||
|
<!-- if jam keluar doesn't exist , then show "-" -->
|
||||||
|
{% if data[i]['jam_keluar'] %}
|
||||||
|
<td>{{data[i]['jam_masuk']}}</td>
|
||||||
|
<td>{{data[i]['jam_keluar']}}</td>
|
||||||
|
{% else %}
|
||||||
|
<td>{{data[i]['jam_masuk']}}</td>
|
||||||
|
<td>-</td>
|
||||||
|
{% endif %}
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
{% else %}
|
||||||
|
<tr>
|
||||||
|
<td colspan="3" class="text-center">Tidak ada data</td>
|
||||||
|
</tr>
|
||||||
|
{% endif %}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-xs-2 col-md-2"></div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
@ -100,6 +154,10 @@
|
||||||
<!-- Full Screen Plugin -->
|
<!-- Full Screen Plugin -->
|
||||||
<script src="assets/plugin/fullscreen/jquery.fullscreen-min.js"></script>
|
<script src="assets/plugin/fullscreen/jquery.fullscreen-min.js"></script>
|
||||||
|
|
||||||
|
<!-- Data Tables -->
|
||||||
|
<script src="assets/plugin/datatables/media/js/jquery.dataTables.min.js"></script>
|
||||||
|
<script src="assets/plugin/datatables/media/js/dataTables.bootstrap.min.js"></script>
|
||||||
|
|
||||||
<script src="assets/scripts/main.min.js"></script>
|
<script src="assets/scripts/main.min.js"></script>
|
||||||
<script>
|
<script>
|
||||||
function goto(stat) {
|
function goto(stat) {
|
||||||
|
|
|
@ -0,0 +1,151 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
|
||||||
|
<head>
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||||
|
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no">
|
||||||
|
<meta name="description" content="">
|
||||||
|
<meta name="author" content="">
|
||||||
|
|
||||||
|
<title>Sistem Absensi - Halaman Utama</title>
|
||||||
|
|
||||||
|
<!-- Main Styles -->
|
||||||
|
<link rel="stylesheet" href="assets/styles/style-horizontal.min.css">
|
||||||
|
|
||||||
|
<!-- mCustomScrollbar -->
|
||||||
|
<link rel="stylesheet" href="assets/plugin/mCustomScrollbar/jquery.mCustomScrollbar.min.css">
|
||||||
|
|
||||||
|
<!-- Waves Effect -->
|
||||||
|
<link rel="stylesheet" href="assets/plugin/waves/waves.min.css">
|
||||||
|
|
||||||
|
<!-- Sweet Alert -->
|
||||||
|
<link rel="stylesheet" href="assets/plugin/sweet-alert/sweetalert.css">
|
||||||
|
|
||||||
|
<!-- Color Picker -->
|
||||||
|
<link rel="stylesheet" href="assets/color-switcher/color-switcher.min.css">
|
||||||
|
<link rel="stylesheet" href="assets/plugin/datatables/media/css/dataTables.bootstrap.min.css">
|
||||||
|
<link rel="stylesheet" href="assets/plugin/datatables/extensions/Responsive/css/responsive.bootstrap.min.css">
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<header class="fixed-header">
|
||||||
|
<div class="header-top">
|
||||||
|
<div class="container">
|
||||||
|
<div class="pull-left">
|
||||||
|
<a href="" class="logo">Sistem Absensi</a>
|
||||||
|
</div>
|
||||||
|
<!-- /.pull-left -->
|
||||||
|
|
||||||
|
<!-- /.pull-right -->
|
||||||
|
</div>
|
||||||
|
<!-- /.container -->
|
||||||
|
</div>
|
||||||
|
<!-- /.header-top -->
|
||||||
|
|
||||||
|
<!-- /.nav-horizontal -->
|
||||||
|
</header>
|
||||||
|
<!-- /.fixed-header -->
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<div id="wrapper">
|
||||||
|
<div class="main-content container">
|
||||||
|
|
||||||
|
<div class="row small-spacing">
|
||||||
|
<div class="col-xs-2 col-md-2"></div>
|
||||||
|
<div class="col-xs-8 col-md-8">
|
||||||
|
<div class="box-content card">
|
||||||
|
<h4 class="box-title">Tanggal : {{today_date}}</h4>
|
||||||
|
<div class="card-content">
|
||||||
|
<table id="example" class="table table-striped table-bordered display" style="width:100%">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<td><b>Nama</b></td>
|
||||||
|
<td><b>Jam Masuk</b></td>
|
||||||
|
<td><b>Jam Keluar</b></td>
|
||||||
|
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{%if data %}
|
||||||
|
|
||||||
|
{% for i in range(0, length) %}
|
||||||
|
|
||||||
|
<tr>
|
||||||
|
<td>{{data[i]['name']}}</td>
|
||||||
|
<!-- if jam keluar doesn't exist , then show "-" -->
|
||||||
|
{% if data[i]['jam_keluar'] %}
|
||||||
|
<td>{{data[i]['jam_masuk']}}</td>
|
||||||
|
<td>{{data[i]['jam_keluar']}}</td>
|
||||||
|
{% else %}
|
||||||
|
<td>{{data[i]['jam_masuk']}}</td>
|
||||||
|
<td>-</td>
|
||||||
|
{% endif %}
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
{% else %}
|
||||||
|
<tr>
|
||||||
|
<td colspan="3" class="text-center">Tidak ada data</td>
|
||||||
|
</tr>
|
||||||
|
{% endif %}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-xs-2 col-md-2"></div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<footer class="footer">
|
||||||
|
<ul class="list-inline">
|
||||||
|
<li>2023 © Naufal.</li>
|
||||||
|
<!-- <li><a href="#">Privacy</a></li>
|
||||||
|
<li><a href="#">Terms</a></li>
|
||||||
|
<li><a href="#">Help</a></li> -->
|
||||||
|
</ul>
|
||||||
|
</footer>
|
||||||
|
</div>
|
||||||
|
<!-- /.main-content -->
|
||||||
|
</div><!--/#wrapper -->
|
||||||
|
<!-- HTML5 shim and Respond.js for IE8 support of HTML5 elements and media queries -->
|
||||||
|
<!--[if lt IE 9]>
|
||||||
|
<script src="assets/script/html5shiv.min.js"></script>
|
||||||
|
<script src="assets/script/respond.min.js"></script>
|
||||||
|
<![endif]-->
|
||||||
|
<!--
|
||||||
|
================================================== -->
|
||||||
|
<!-- Placed at the end of the document so the pages load faster -->
|
||||||
|
<script src="assets/scripts/jquery.min.js"></script>
|
||||||
|
<script src="assets/scripts/modernizr.min.js"></script>
|
||||||
|
<script src="assets/plugin/bootstrap/js/bootstrap.min.js"></script>
|
||||||
|
<script src="assets/plugin/mCustomScrollbar/jquery.mCustomScrollbar.concat.min.js"></script>
|
||||||
|
<script src="assets/plugin/nprogress/nprogress.js"></script>
|
||||||
|
<script src="assets/plugin/sweet-alert/sweetalert.min.js"></script>
|
||||||
|
<script src="assets/plugin/waves/waves.min.js"></script>
|
||||||
|
<!-- Full Screen Plugin -->
|
||||||
|
<script src="assets/plugin/fullscreen/jquery.fullscreen-min.js"></script>
|
||||||
|
|
||||||
|
<!-- Data Tables -->
|
||||||
|
<script src="assets/plugin/datatables/media/js/jquery.dataTables.min.js"></script>
|
||||||
|
<script src="assets/plugin/datatables/media/js/dataTables.bootstrap.min.js"></script>
|
||||||
|
|
||||||
|
<script src="assets/scripts/main.min.js"></script>
|
||||||
|
<script>
|
||||||
|
function goto(stat) {
|
||||||
|
if (stat == 'home') {
|
||||||
|
window.location.href = "{{url_for('home')}}";
|
||||||
|
} else if (stat == 'tambah_karyawan') {
|
||||||
|
window.location.href = "{{url_for('tambah_karyawan')}}";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
|
||||||
|
</html>
|
Loading…
Reference in New Issue