get_field('autoattendmod', 'namepattern', array('course'=>$courseid));
if (!$pattern) $pattern = 'fullname';
return $pattern;
}
//
function autoattendmod_disp_feedback($courseid)
{
global $DB;
if ($courseid==0) return true;
$disp = $DB->get_field('autoattendmod', 'feedback', array('course'=>$courseid));
return $disp;
}
////////////////////////////////////////////////////////////////////////////////////////
//
// Grade
//
//
// 評定を更新する
//
function autoattendmod_update_grades_bycourseid($courseid)
{
global $DB;
$mod = $DB->get_record('autoattendmod', array('course'=>$courseid));
if ($mod) {
$mod->cmidnumber = '';
autoattendmod_update_grades($mod);
}
}
////////////////////////////////////////////////////////////////////////////////////////
//
// Event Log
//
function autoattendmod_get_event($cm, $action, $params='', $info='')
{
global $CFG;
$ver = jbxl_get_moodle_version();
$event = null;
if (!is_array($params)) $params = array();
if (floatval($ver)>=2.7) {
$params = array(
'context' => context_module::instance($cm->id),
'other' => array('params' => $params, 'info'=> $info),
);
if ($action=='view') {
$event = \mod_autoattendmod\event\view_log::create($params);
}
else if ($action=='update') {
$event = \mod_autoattendmod\event\attendaction_update::create($params);
}
else if ($action=='delete') {
$event = \mod_autoattendmod\event\delete_del::create($params);
}
else if ($action=='submit') {
$event = \mod_autoattendmod\event\semiautoattendmod_submit::create($params);
}
else {
$event = \mod_autoattendmod\event\view_log::create($params);
}
}
// for Legacy add_to_log()
else {
if ($action=='view') {
$file = 'view.php';
}
else if ($action=='update') {
$file = 'attendaction.php';
}
else if ($action=='delete') {
$file = 'delete.php';
}
else if ($action=='submit') {
$file = 'semiautoattend.php';
}
else {
$file = 'view.php';
}
$param_str = jbxl_get_url_params_str($params);
$event = new stdClass();
$event->courseid= $cm->course;
$event->name = 'autoattendmod';
$event->action = $action;
$event->url = $file.$param_str;
$event->info = $info;
}
return $event;
}
////////////////////////////////////////////////////////////////////////////////////////
//
// E-Mail
//
// メール受信可能なユーザ
function autoattendmod_get_receivemail_users($context)
{
$ret = get_users_by_capability($context, 'mod/autoattendmod:receivemail', '', 'lastname', '', '', false, '', false);
return $ret;
}
//
function autoattendmod_is_email_enable($courseid)
{
global $DB;
if ($courseid==0) return false;
$enable = $DB->get_field('autoattendmod', 'emailenable', array('course'=>$courseid));
return $enable;
}
//
function autoattendmod_is_email_allreports($courseid)
{
global $DB;
if ($courseid==0) return false;
$allrep = $DB->get_field('autoattendmod', 'allreports', array('course'=>$courseid));
return $allrep;
}
//
function autoattendmod_is_email_key($courseid)
{
global $DB;
if ($courseid==0) return false;
$enable = $DB->get_field('autoattendmod', 'emailkey', array('course'=>$courseid));
return $enable;
}
//
function autoattendmod_is_email_user($courseid)
{
global $DB;
if ($courseid==0) return false;
$enable = $DB->get_field('autoattendmod', 'emailuser', array('course'=>$courseid));
return $enable;
}
//
function autoattendmod_email_text($info, $mesg, $ttle)
{
$posttext = $info->shortname.' ['.$info->date.' '.$info->starttm.'-'.$info->endtm.']';
$posttext .= "\n--------------------------------------------------------------------------\n";
$posttext .= get_string($ttle, 'autoattendmod')."\n\n";
$posttext .= get_string($mesg, 'autoattendmod', $info)."\n";
$posttext .= "\n--------------------------------------------------------------------------\n";
return $posttext;
}
//
function autoattendmod_email_html($info, $mesg, $ttle)
{
$posthtml = '
'.$info->shortname.' ['.$info->date.' '.$info->starttm.'-'.$info->endtm.']
'."\n";
$posthtml .= ''.get_string($ttle, 'autoattendmod').'
'."\n";
$posthtml .= ''."\n";
$posthtml .= get_string($mesg, 'autoattendmod', $info)."\n";
$posthtml .= '
';
return $posthtml;
}
//
function autoattendmod_send_email_teachers($courseid, $subject, $posttext, $posthtml, $attachdata, $attachname)
{
global $CFG;
require_once($CFG->dirroot.'/mod/autoattendmod/jbxl/jbxl_moodle_tools.php');
$ccontext = context_course::instance($courseid);
$teachers = autoattendmod_get_receivemail_users($ccontext);
if ($teachers) {
foreach ($teachers as $teacher) {
if (jbxl_is_teacher($teacher->id, $ccontext, false)) {
$htmlmail = '';
if ($teacher->mailformat==1) {
$htmlmail = $posthtml;
}
email_to_user($teacher, 'AutoAttendanceModule', $subject, $posttext, $htmlmail, $attachdata, $attachname);
}
}
}
}
function autoattendmod_email_teachers_attend($sess)
{
global $DB, $TIME_OFFSET;
if (!file_exists($CFG->tempdir.'/autoattendmod')) {
mkdir($CFG->tempdir.'/autoattendmod');
}
//
$courseid = $sess->courseid;
$course = $DB->get_record('course', array('id'=>$courseid));
$classes = autoattendmod_get_session_classes($courseid);
$daytime = strftime(get_string('strftimedmyw', 'autoattendmod'), $sess->sessdate+$TIME_OFFSET);
$starttm = strftime(get_string('strftimehourmin', 'autoattendmod'), $sess->starttime + $TIME_OFFSET);
$endtm = strftime(get_string('strftimehourmin', 'autoattendmod'), $sess->endtime + $TIME_OFFSET);
$pathname = $CFG->tempdir.'/autoattendmod/attendance_'.$sess->id.'_'.date('YmdHis').'.$$$';
$filename = get_string('attendance', 'autoattendmod').'_'.$course->fullname.'_'.$daytime.'.csv';
$datas = autoattendmod_make_download_data($courseid, $classes, 0, 'all', 0, $sess->id);
jbxl_save_csv_file($datas, $pathname);
$info = new stdClass();
$info->shortname = $course->shortname;
$info->fullname = $course->fullname;
$info->date = $daytime;
$info->starttm = $starttm;
$info->endtm = $endtm;
$posttext = autoattendmod_email_text($info, 'email_teacher_attend', 'attenddata');
$posthtml = autoattendmod_email_html($info, 'email_teacher_attend', 'attenddata');
$subject = get_string('attenddata', 'autoattendmod').': '.$course->fullname.': '.$daytime.' '.$starttm.'-'.$endtm;
autoattendmod_send_email_teachers($courseid, $subject, $posttext, $posthtml, $pathname, $filename);
unlink($pathname);
return;
}
function autoattendmod_email_teachers_key($sess)
{
global $DB, $TIME_OFFSET;
$courseid = $sess->courseid;
$course = $DB->get_record('course', array('id'=>$courseid));
$daytime = strftime(get_string('strftimedmyw', 'autoattendmod'), $sess->sessdate+$TIME_OFFSET);
$starttm = strftime(get_string('strftimehourmin', 'autoattendmod'), $sess->starttime + $TIME_OFFSET);
$endtm = strftime(get_string('strftimehourmin', 'autoattendmod'), $sess->endtime + $TIME_OFFSET);
$info = new stdClass();
$info->shortname = $course->shortname;
$info->fullname = $course->fullname;
$info->key = $sess->attendkey;
$info->date = $daytime;
$info->starttm = $starttm;
$info->endtm = $endtm;
$posttext = autoattendmod_email_text($info, 'email_teacher_key', 'attendkey');
$posthtml = autoattendmod_email_html($info, 'email_teacher_key_html', 'attendkey');
$subject = get_string('attendkey', 'autoattendmod').': '.$course->fullname.': '.$daytime.' '.$starttm.'-'.$endtm;
autoattendmod_send_email_teachers($courseid, $subject, $posttext, $posthtml, null, null);
return;
}
function autoattendmod_email_user($sess, $user, $status)
{
global $DB, $TIME_OFFSET;
$courseid = $sess->courseid;
$course = $DB->get_record('course', array('id'=>$courseid));
$daytime = strftime(get_string('strftimedmyw', 'autoattendmod'), $sess->sessdate+$TIME_OFFSET);
$starttm = strftime(get_string('strftimehourmin', 'autoattendmod'), $sess->starttime + $TIME_OFFSET);
$endtm = strftime(get_string('strftimehourmin', 'autoattendmod'), $sess->endtime + $TIME_OFFSET);
$info = new stdClass();
$info->shortname = $course->shortname;
$info->fullname = $course->fullname;
$info->date = $daytime;
$info->starttm = $starttm;
$info->endtm = $endtm;
if ($status=='P') {
$posttext = autoattendmod_email_text($info, 'email_user_attend_P', 'attendanceconfrm');
$posthtml = autoattendmod_email_html($info, 'email_user_attend_P', 'attendanceconfrm');
}
else if ($status=='X') {
$posttext = autoattendmod_email_text($info, 'email_user_attend_X', 'attendanceconfrm');
$posthtml = autoattendmod_email_html($info, 'email_user_attend_X', 'attendanceconfrm');
}
else if ($status=='L') {
$posttext = autoattendmod_email_text($info, 'email_user_attend_L', 'attendanceconfrm');
$posthtml = autoattendmod_email_html($info, 'email_user_attend_L', 'attendanceconfrm');
}
else {
$posttext = autoattendmod_email_text($info, 'email_user_attend_C', 'attendanceconfrm');
$posthtml = autoattendmod_email_html($info, 'email_user_attend_C', 'attendanceconfrm');
}
$subject = get_string('attendanceconfrm', 'autoattendmod').': '.$course->fullname.': '.$daytime.' '.$starttm.'-'.$endtm;
email_to_user($user, 'AutoAttendanceModule', $subject, $posttext, $posthtml, null, null);
return;
}
/*
function autoattendmod_to_localcode($message, $tocode)
function autoattendmod_get_sessions($courseid, $classid, $inall=false)
function autoattendmod_count_sessions($courseid, $classid)
*/
/////////////////////////////////////////////////////////////////////////////////////////////
//
//
function autoattendmod_to_localcode($message, $tocode)
{
return mb_convert_encoding($message, $tocode, 'auto');
}
/////////////////////////////////////////////////////////////////////////////////////////////
//
// Sessions
//
//
// コースの講義情報を得る
//
// $inall : クラスIDを指定した時に,さらに全学生用クラス(クラスID=0)を含むか?
//
function autoattendmod_get_sessions($courseid, $classid, $inall=false)
{
global $DB;
$sort = 'sessdate, starttime ASC';
if ($classid==0) {
$sessions = $DB->get_records('autoattendmod_sessions', array('course'=>$courseid), $sort);
}
else {
$params = array('course'=>$courseid, 'classid'=>$classid);
if ($inall) {
$select = 'course=:courseid AND (classid=:classid OR classid=0)';
$sessions = $DB->get_records_select('autoattendmod_sessions', $select, $params, $sort);
}
else {
$sessions = $DB->get_records('autoattendmod_sessions', $params, $sort);
}
}
return $sessions;
}
//
// まだ始まってない講義の数を数える. $classidを指定した場合でも,$classid=0 のクラスを含む.
//
function autoattendmod_count_sessions($courseid, $classid)
{
global $DB;
$select = "course=$courseid AND state<>'N' AND (classid=$classid OR classid=0)";
$sescount = $DB->count_records_select('autoattendmod_sessions', $select);
if (!$sescount) $sescount = 0;
return $sescount;
}
/*
function autoattendmod_get_attend_students($courseid, $classid=0, $context=null, $sort='', $order='')
function autoattendmod_count_attend_students($courseid, $classid=0, $context=null)
function autoattendmod_count_class_students($session, $courseid, $context, $select='')
function autoattendmod_insert_session_class($courseid, $classname)
function autoattendmod_update_session_classes(array $classids, array $classnames, array $classdels)
function autoattendmod_get_user_class($userid, $courseid, $idonly=false)
function autoattendmod_get_session_classes($courseid)
function autoattendmod_get_user_classname($classid)
function autoattendmod_get_session_classname($classid)
function autoattendmod_select_session_class($classid, $classes, $url, $url_options)
function autoattendmod_select_user_class($classid, $classes, $url, $url_options, $show_ex=false)
function autoattendmod_select_attend($attend, $url, $url_options)
function autoattendmod_choose_grouping($courseid, $url, $url_options) // by Emilio Arjona
function autoattendmod_get_grade_settings($courseid)
function autoattendmod_update_grade_settings($courseid, array settings, $restore=0)
function autoattendmod_get_status_num($userid, $courseid, $status)
function autoattendmod_get_grade($userid, $courseid)
function autoattendmod_get_user_summary($userid, $courseid)
function autoattendmod_get_session_summary($courseid)
function autoattendmod_print_user_row($left, $right)
function autoattendmod_print_user($user, $course, $printing=null)
function autoattendmod_get_nowopen_sessions($courseid, $stdntid, $method, $ntime)
function autoattendmod_get_users_bystatus($sessid, $statuss='')
//function autoattendmod_get_user_atsession($sessid, $userid)
function autoattendmod_get_unclosed_sessions($courseid, $methods='', $ntime='', $incopen=false)
function autoattendmod_add_user_insession($sessid, $userid)
//function autoattendmod_reset_session_user($courseid, $sessid)
//function autoattendmod_update_sessions_user($courseid, $stdntid, $ntime='')
function autoattendmod_update_session_users($courseid, $sessid, $ntime='')
//function autoattendmod_update_sessions_users($courseid, $ntime='')
function autoattendmod_update_session_state($courseid, $sess, $ntime='', $regist=true)
function autoattendmod_update_sessions_state($coueseid, $sesss, $ntime='', $regist=true)
function autoattendmod_update_session($courseid, $sessid, $ntime='')
function autoattendmod_update_sessions($courseid, $ntime='')
function autoattendmod_update_auto_session($courseid, $sess, $logs, $ntime='')
function autoattendmod_close_session($courseid, $sess, $ntime='')
function autoattendmod_return_to_Y($sessid)
function autoattendmod_check_valid_logip($userlogs, $ipfmts, $used_ips, $difipf)
function autoattendmod_check_invalid_semiautoip($att)
function autoattendmod_get_usedips($attsid)
function autoattendmod_get_courselogs($courseid, $stime, $etime=0)
//function autoattendmod_get_courselogs_pastdays($courseid, $day=0)
function autoattendmod_get_ipresolv_url($ip)
*/
/////////////////////////////////////////////////////////////////////////////////////////////
//
// Students
//
//
// クラスに属する学生を得る.
// $classid==0 の場合は全クラスに属する学生を帰す.
//
function autoattendmod_get_attend_students($courseid, $classid=0, $context=null, $sort='', $order='')
{
$students = array();
if (!$courseid) return $students;
if (!$context) $context = jbxl_get_course_context($courseid);
if ($sort!='' and $order!='') $sort .= ' '.$order;
$users = jbxl_get_course_students($context, $sort);
if ($users) {
foreach ($users as $user) {
$classinfo = autoattendmod_get_user_class($user->id, $courseid);
if ($classinfo->classid>=0 and (($classinfo->classid==$classid or $classid==0) or
($classid==NON_CLASSID and $classinfo->classid==0))) {
$students[$user->id] = new stdClass();
$students[$user->id]->id = $user->id;
$students[$user->id]->firstname = $user->firstname;
$students[$user->id]->lastname = $user->lastname;
$students[$user->id]->idnumber = $user->idnumber;
$students[$user->id]->fullname = fullname($user);
$students[$user->id]->classid = $classinfo->classid;
$students[$user->id]->classname = $classinfo->name;
$students[$user->id]->user = $user;
}
}
}
return $students;
}
//
// クラスに属する学生の人数を得る.
// $classid==0 の場合は全クラスに属する学生を帰す.
//
function autoattendmod_count_attend_students($courseid, $classid=0, $context=null)
{
if (!$courseid) return 0;
if (!$context) $context = jbxl_get_course_context($courseid);
$count = 0;
$users = jbxl_get_course_students($context, '');
if ($users) {
foreach ($users as $user) {
$classinfo = autoattendmod_get_user_class($user->id, $courseid, true);
if ($classinfo->classid>=0 and (($classinfo->classid==$classid or $classid==0) or
($classid==NON_CLASSID and $classinfo->classid==0))) {
$count++;
}
}
}
return $count;
}
//
// 条件を指定して,出席レコードを用いて学生の数を数える.
//
// ただし,出席レコードの存在する学生のみ (つまり,statusがYの学生はカウントされない可能性がある)
// 出席レコードの存在しない学生も正確にカウントしたい場合は autoattendmod_count_attend_students() を用いる.
// また,欠席から除外された学生はカウントされない.
//
// クラスを指定する場合は $session->classid にクラスIDを設定する.
//
// 出席(含む遅刻,早退)した学生の数: $select = "status<>'Y' AND status<>'X'"
//
function autoattendmod_count_class_students($session, $courseid, $context, $select='')
{
global $DB;
if (empty($select)) $select = 'attsid=?';
else $select = 'attsid=? AND '.$select;
$count = 0;
$users = $DB->get_records_select('autoattendmod_students', $select, array($session->id));
if ($users) {
foreach ($users as $user) {
$classinfo = autoattendmod_get_user_class($user->studentid, $courseid, true);
if ($classinfo->classid>=0) {
if ($classinfo->classid==$session->classid or $session->classid==0) $count++;
}
}
}
return $count;
}
/////////////////////////////////////////////////////////////////////////////////////////////
//
// Class
//
//
//
// 講義のクラスをDB上に作成
//
function autoattendmod_insert_session_class($courseid, $classname)
{
global $DB, $USER;
$rec = new stdClass();
$rec->name = $classname;
$rec->courseid = $courseid;
$rec->creator = $USER->id;
$rec->timemodified = time();
return $DB->insert_record('autoattendmod_classes', $rec);
}
//
// 講義のクラス情報(名前)を更新 または削除
//
function autoattendmod_update_session_classes(array $classids, array $classnames, array $classdels)
{
global $DB, $USER;
foreach ($classids as $key=>$classid) {
if (isset($classdels[$key])) {
$DB->delete_records('autoattendmod_classes', array('id'=>$classid));
}
else {
$rec = $DB->get_record('autoattendmod_classes', array('id'=>$classid));
if (strcmp($rec->name, $classnames[$key])) {
$rec->name = $classnames[$key];
$rec->creator = $USER->id;
$rec->timemodified = time();
$DB->update_record('autoattendmod_classes', $rec);
}
}
}
}
//
// 学生の所属するクラスの情報を取得
// idonly: class id のみを取得する.高速化用.
//
function autoattendmod_get_user_class($userid, $courseid, $idonly=false)
{
global $DB;
$class = $DB->get_record('autoattendmod_classifies', array('course'=>$courseid, 'studentid'=>$userid));
if (!$class) {
$class = new stdClass();
$class->id = 0;
$class->courseid = $courseid;
$class->studentid = $userid;
$class->classid = 0;
}
if (!$idonly) $class->name = autoattendmod_get_user_classname($class->classid);
return $class;
}
//
// 講義の全クラスの情報を取得
//
function autoattendmod_get_session_classes($courseid)
{
global $DB;
$results = $DB->get_records('autoattendmod_classes', array('course'=>$courseid), 'id');
$classes = array();
/*
$classes[0] = new stdClass();
$classes[0]->id = 0;
$classes[0]->courseid = $courseid;
$classes[0]->creator = 0;
$classes[0]->name = get_string('allstudents', 'autoattendmod');
$classes[0]->timemodified = time();
*/
if ($results) {
foreach($results as $result) {
$classes[$result->id] = $result;
}
}
return $classes;
}
//
// 学生の所属するクラスの名前を取得
//
function autoattendmod_get_user_classname($classid)
{
global $DB;
if ($classid==0) return get_string('nonclass', 'autoattendmod');
else if ($classid==-1) return get_string('exclusion', 'autoattendmod');
$class = $DB->get_record('autoattendmod_classes', array('id'=>$classid));
if (!$class) return get_string('unknownclass', 'autoattendmod');
return $class->name;
}
//
// 講義のクラス名を取得
//
function autoattendmod_get_session_classname($classid)
{
global $DB;
if ($classid==0) return get_string('allstudents', 'autoattendmod');
$class = $DB->get_record('autoattendmod_classes', array('id'=>$classid));
if (!$class) return get_string('unknownclass', 'autoattendmod');
return $class->name;
}
//
// 講義のクラスの選択ボックスを表示する.
//
function autoattendmod_select_session_class($classid, $classes, $url, $url_options)
{
global $OUTPUT;
if ($classes) {
$popupurl = $url.$url_options;
//
$options = array();
$options[0] = get_string('allclasses', 'autoattendmod');
if ($classes) {
foreach ($classes as $class) {
$options[$class->id] = $class->name;
}
}
//
echo $OUTPUT->single_select($popupurl, 'class', $options, $classid);
}
}
//
// by Emilio Arjona 2015
//
function autoattendmod_choose_grouping($courseid, $url, $url_options)
{
global $OUTPUT;
$options = array();
$groupings = groups_get_all_groupings($courseid);
if ($groupings){
$popupurl = $url.$url_options;
foreach ($groupings as $grouping) {
$options [$grouping->id] = $grouping->name;
}
$options[0] = get_string('allgrouping', 'autoattendmod');
}
return $options;
}
//
// ユーザクラスの選択ボックスを表示する.
//
function autoattendmod_select_user_class($classid, $classes, $url, $url_options, $show_ex=false)
{
global $OUTPUT;
if ($classes or $show_ex) {
$popupurl = $url.$url_options;
//
$options = array();
$options[0] = get_string('allclasses', 'autoattendmod');
if ($show_ex) $options[VALID_CLASSID] = get_string('validclasses', 'autoattendmod');
if ($classes) {
$options[NON_CLASSID] = get_string('nonclass', 'autoattendmod');
foreach ($classes as $class) {
$options[$class->id] = $class->name;
}
}
if ($show_ex) $options[-1] = get_string('excludedstudents', 'autoattendmod');
//
echo $OUTPUT->single_select($popupurl, 'class', $options, $classid);
}
}
//
function autoattendmod_select_attend($attend, array $settings, $url, $url_options)
{
global $OUTPUT;
$popupurl = $url.$url_options;
//
$options = array();
$options['A'] = get_string('Adesc', 'autoattendmod');
$options['P'] = $settings['P']->description;
$options['L'] = $settings['L']->description;
$options['E'] = $settings['E']->description;
$options['X'] = $settings['X']->description;
$options['Y'] = $settings['Y']->description;
$options['Z'] = $options['X'].' or '.$options['Y'];
//
echo $OUTPUT->single_select($popupurl, 'attend', $options, $attend);
}
/////////////////////////////////////////////////////////////////////////////////////////////
//
// Grade
//
//
// 評定の点数設定を得る
//
function autoattendmod_get_grade_settings($courseid)
{
global $DB;
$result= $DB->get_records('autoattendmod_settings', array('course'=>$courseid), 'id');
if (!$result) {
$result = $DB->get_records('autoattendmod_settings', array('course'=>0), 'id'); // use default
}
$settings = array();
foreach ($result as $res) {
if (empty($res->acronym)) $res->acronym = get_string($res->status.'acronym', 'autoattendmod');
if (empty($res->title)) $res->title = get_string($res->status.'title', 'autoattendmod');
if (empty($res->description)) $res->description = get_string($res->status.'desc', 'autoattendmod');
$settings[$res->status] = $res;
}
return $settings;
}
//
// 評定の点数設定を更新する
//
function autoattendmod_update_grade_settings($courseid, array $settings, $restore=0)
{
global $DB;
if (empty($courseid)) $courseid = 0;
//restore defaults
if ($restore) {
if ($courseid!=0) {
$DB->delete_records('autoattendmod_settings', array('course'=>$courseid));
}
return;
}
if (!$settings) return;
//
$status = array('P','L','E','X','Y');
for ($i=0; $iget_record('autoattendmod_settings', array('course'=>$courseid, 'status'=>$status[$i]))) {
$update = true;
}
else {
$rec = new stdClass();
$rec->classid = 0;
$update = false;
}
$rec->courseid = $courseid;
$rec->status = $status[$i];
$rec->grade = $settings[$status[$i]]->grade;
$rec->acronym = $settings[$status[$i]]->acronym;
$rec->title = $settings[$status[$i]]->title;
$rec->description = $settings[$status[$i]]->description;
if ($update) {
$result = $DB->update_record('autoattendmod_settings', $rec);
if (!$result) break;
}
else {
$result = $DB->insert_record('autoattendmod_settings', $rec);
if (!$result) break;
}
unset($rec);
}
}
//
// 出席や欠席の回数を返す
// $status に 'P', 'L', 'E', 'X', 'Y' を指定する
//
function autoattendmod_get_status_num($userid, $courseid, $status)
{
global $CFG, $DB;
$classinfo = autoattendmod_get_user_class($userid, $courseid);
$qry = "SELECT COUNT(*) AS cnt FROM {$CFG->prefix}autoattendmod_students std ,{$CFG->prefix}autoattendmod_sessions ses".
" WHERE std.attsid = ses.id AND ses.courseid = ".$courseid ." AND std.studentid = ".$userid.
" AND std.status = '".$status."' AND (ses.classid = ".$classinfo->classid." OR ses.classid = 0)";
//print "QUERY=> $qry
";
$data = $DB->get_record_sql($qry);
return $data->cnt;
}
//
// 出席点を返す
//
function autoattendmod_get_grade($userid, $courseid)
{
$settings = autoattendmod_get_grade_settings($courseid);
$grade = 0;
foreach ($settings as $setting) {
$count = autoattendmod_get_status_num($userid, $courseid, $setting->status);
$grade = $grade + $count * $setting->grade;
}
return $grade;
}
/////////////////////////////////////////////////////////////////////////////////////////////
//
// Summary
//
//
// 学生のサマリーを返す
//
// $summary['userid'] : ユーザID
// $summary['course'] : コースID
// $summary['attitems'] : 学生の各授業のRawデータ(配列)
// $summary['complete'] : 出席コマ数(早退,遅刻を含む)
// $summary['settings'] : 出席点の配分Rawデータ(配列)
// $summary['grade'] : 出席点
// $summary['percent'] : 出席率(出席点ベース)
// $summary['P'] : 正常出席数
// $summary['X'] : 欠席数.クローズしたセッションで Y の物を含む.
// $summary['L'] : 遅刻数
// $summary['E'] : 早退数
// $summary['Y'] : 未了数.ただしクローズしたセッションは X とする.
// $summary['classid'] : クラスID
// $summary['classname']: クラス名
// $summary['maxgrade'] : 最高出席点(皆勤の場合の出席点)
// $summary['mingrade'] : 最低出席点(全欠の場合の出席点)
// $summary['leccount'] : 実施した授業のコマ数
//
function autoattendmod_get_user_summary($userid, $courseid)
{
global $CFG, $DB;
require_once('jbxl/jbxl_moodle_tools.php');
$ntime = time();
$class = autoattendmod_get_user_class($userid, $courseid);
$stqry = "SELECT * FROM {$CFG->prefix}autoattendmod_students std".
" RIGHT JOIN (SELECT * FROM {$CFG->prefix}autoattendmod_sessions WHERE courseid=$courseid) ses".
" ON ses.id=std.attsid AND std.studentid=$userid AND (ses.classid=".$class->classid." OR ses.classid=0)".
" ORDER BY ses.sessdate, ses.starttime ASC";
$attitems = $DB->get_records_sql($stqry);
if (!$attitems) return false;
$summary = array();
$summary['userid'] = $userid;
$summary['course'] = $courseid;
$summary['attitems'] = $attitems;
$complete = 0;
if ($attitems) {
foreach($attitems as $att) {
if (!empty($att->status) && $att->status!='Y') $complete++;
}
}
$summary['complete'] = $complete; // 出席コマ数(早退,遅刻を含む)
$summary['settings'] = autoattendmod_get_grade_settings($courseid);
$maxgrade = 0;
$mingrade = 0;
foreach($summary['settings'] as $set) {
$summary[$set->status] = 0;
foreach($summary['attitems'] as $att) {
if ($set->status==$att->status) {
// 出席の状態をカウント
if ($att->status=='Y') {
if ($ntime>$att->endtime) $summary['X']++;
//else $summary['Y']++;
}
else {
$summary[$set->status]++;
}
}
}
if ($set->grade>$maxgrade) $maxgrade = $set->grade;
if ($set->grade<$mingrade) $mingrade = $set->grade;
}
$sessnum = autoattendmod_count_sessions($courseid, $class->classid);
$summary['Y'] = $sessnum - $summary['P'] - $summary['L'] - $summary['E'] - $summary['X'];
//
$summary['grade'] = autoattendmod_get_grade($userid, $courseid);
$summary['maxgrade'] = $maxgrade*$sessnum;
$summary['mingrade'] = $mingrade*$sessnum;
$summary['leccount'] = $sessnum;
//
$gradelevel = $summary['maxgrade'] - $summary['mingrade'];
if ($gradelevel!=0) {
$percent = 100*($summary['grade']-$summary['mingrade'])/$gradelevel;
$summary['percent'] = sprintf('%0.1f', $percent);
}
else {
$summary['percent'] = ' - ';
}
$summary['classid'] = $class->classid;
$summary['classname']= $class->name;
return $summary;
}
//
// 授業の全クラスのサマリーを返す
//
// $summary['course'] : コースID
// $summary['attitems'] : 各授業のRawデータ(配列)
// $summary['classes'] : クラスデータ(配列)
// $summary['settings'] : 出席点の配分Rawデータ(配列)
// $summary['maxgrade'] : 実施された授業での最高出席点(皆勤の場合の出席点)
// $summary['mingrade'] : 実施された授業での最低出席点(全欠場合の出席点)
// $summary['leccount'] : 実施された授業のコマ数
//
function autoattendmod_get_session_summary($courseid)
{
global $DB;
require_once('jbxl/jbxl_moodle_tools.php');
$attitems = $DB->get_records('autoattendmod_sessions', array('course'=>$courseid), 'starttime');
if (!$attitems) return false;
$summary = array();
$summary['course'] = $courseid;
$summary['attitems'] = $attitems;
$summary['settings'] = autoattendmod_get_grade_settings($courseid);
$summary['classes'] = autoattendmod_get_session_classes($courseid);
//
$attpoint = 0;
$abspoint = 0;
foreach($summary['settings'] as $set) {
if ($set->grade>$attpoint) $attpoint = $set->grade;
if ($set->grade<$abspoint) $abspoint = $set->grade;
}
$leccount = 0;
if (!$summary['classes']) {
$summary['classes'][0] = new stdClass();
$summary['classes'][0]->id = 0;
$summary['classes'][0]->courseid = $courseid;
$summary['classes'][0]->creator = 0;
$summary['classes'][0]->name = get_string('allstudents', 'autoattendmod');
$summary['classes'][0]->timemodified = time();
}
// クラスによってコマ数が違う場合
foreach ($summary['classes'] as $class) {
$count = 0;
foreach ($attitems as $att) {
if ($att->state<>'N' and ($att->classid==$class->id or $att->classid==0)) $count++;
}
if ($count>$leccount) $leccount = $count;
}
$summary['maxgrade'] = $attpoint*$leccount;
$summary['mingrade'] = $abspoint*$leccount;
$summary['leccount'] = $leccount;
return $summary;
}
/////////////////////////////////////////////////////////////////////////////////////////////
//
// View and Print
//
function autoattendmod_print_user_row($left, $right)
{
echo "\n$left |
$right |
\n";
}
//
// 1ユーザの出欠レポートを表示する
//
function autoattendmod_print_user($user, $course, $printing=null)
{
global $DB, $CFG, $USER, $OUTPUT, $TIME_OFFSET;
$wwwBlock = $CFG->wwwroot.'/blocks/autoattend';
$wwwGrade = $CFG->wwwroot.'/grade/report/user';
$wwwReport = $CFG->wwwroot.'/report/log';
$wwwMesg = $CFG->wwwroot.'/message';
$wwwUser = $CFG->wwwroot.'/user';
if (!is_object($course)) {
$course = $DB->get_record('course', array('id'=>$course));
}
$courseid = $course->id;
$userid = $user->id;
$context = jbxl_get_course_context($courseid);
$isteacher = jbxl_is_teacher($USER->id, $context);
$summary = autoattendmod_get_user_summary($user->id, $courseid);
if(!$summary) {
notice(get_string('attendnotstarted','autoattendmod'), $CFG->wwwroot.'/course/view.php?id='.$courseid);
}
else {
$complete = $summary['complete'];
$percent = $summary['percent'].' %';
$grade = $summary['grade'];
$maxgrade = $summary['maxgrade'];
$settings = $summary['settings'];
$classid = $summary['classid'];
$classname = $summary['classname'];
//
if ($CFG->output_idnumber) {
if (empty($user->idnumber)) $user_idnum = ' - ';
else $user_idnum = $user->idnumber;
$disp_idnum = '['.$user_idnum.']';
}
else {
$user_idnum = '';
$disp_idnum = '';
}
//
$name_pattern = autoattendmod_get_namepattern($courseid);
$username = jbxl_get_user_name($user->id, $name_pattern);
include('html/print_user_header.html');
//
if ($classid>=0) { // !出欠から除外
//
$table = new html_table();
// Header
$table->head [] = '#';
$table->align[] = 'right';
$table->size [] = '20px';
$table->wrap [] = 'nowrap';
$table->head [] = get_string('date');
$table->align[] = 'center';
$table->size [] = '40px';
$table->wrap [] = 'nowrap';
$table->head [] = get_string('starttime', 'autoattendmod');
$table->align[] = 'center';
$table->size [] = '60px';
$table->wrap [] = 'nowrap';
$table->head [] = get_string('endtime', 'autoattendmod');
$table->align[] = 'center';
$table->size [] = '60px';
$table->wrap [] = 'nowrap';
$table->head [] = get_string('classname', 'autoattendmod');
$table->align[] = 'center';
$table->size [] = '40px';
$table->wrap [] = 'nowrap';
$table->head [] = get_string('description','autoattendmod');
$table->align[] = 'left';
$table->size [] = '40px';
$table->wrap [] = 'nowrap';
$table->head [] = get_string('status', 'autoattendmod');
$table->align[] = 'center';
$table->size [] = '40px';
$table->wrap [] = 'nowrap';
$table->head [] = get_string('callmethod', 'autoattendmod');
$table->align[] = 'center';
$table->size [] = '60px';
$table->wrap [] = 'nowrap';
$table->head [] = get_string('calledtime', 'autoattendmod');
$table->align[] = 'center';
$table->size [] = '60px';
$table->wrap [] = 'nowrap';
$table->head [] = get_string('ip', 'autoattendmod');
$table->align[] = 'center';
$table->size [] = '80px';
$table->wrap [] = 'nowrap';
$table->head [] = get_string('remarks', 'autoattendmod');
$table->align[] = 'center';
$table->size [] = '120px';
$table->wrap [] = 'nowrap';
$i = 0;
foreach($summary['attitems'] as $att) {
if ($att->classid==$classid or $att->classid==0) {
$table->data[$i][] = $i + 1;
$table->data[$i][] = strftime(get_string('strftimedmyw', 'autoattendmod'), $att->sessdate + $TIME_OFFSET);
$table->data[$i][] = strftime(get_string('strftimehourmin','autoattendmod'), $att->starttime + $TIME_OFFSET);
$table->data[$i][] = strftime(get_string('strftimehourmin','autoattendmod'), $att->endtime + $TIME_OFFSET);
$table->data[$i][] = autoattendmod_get_user_classname($att->classid);
$table->data[$i][] = $att->description ? $att->description: get_string('nodescription', 'autoattendmod');
if ($att->studentid) {
if ($att->status=='Y') {
if (time()>$att->endtime) {
$table->data[$i][] = $settings['X']->acronym;
}
else {
$table->data[$i][] = get_string('novalue', 'autoattendmod');
}
}
else {
$table->data[$i][] = $settings[$att->status]->acronym;
}
$table->data[$i][] = get_string($att->called.'methodfull', 'autoattendmod');
}
else {
$table->data[$i][] = get_string('novalue', 'autoattendmod');
$table->data[$i][] = get_string('novalue', 'autoattendmod');
}
//
if (!$att->studentid OR $att->status==='X' OR $att->status==='Y') {
$table->data[$i][] = get_string('novalue', 'autoattendmod');;
}
else {
$sessndate = strftime(get_string('strftimedmshort', 'autoattendmod'), $att->sessdate + $TIME_OFFSET);
$calleddate = strftime(get_string('strftimedmshort', 'autoattendmod'), $att->calledtime + $TIME_OFFSET);
$calledtime = strftime(get_string('strftimehmshort', 'autoattendmod'), $att->calledtime + $TIME_OFFSET);
//$table->data[$i][] = strftime(get_string('strftimecalled', 'autoattendmod'), $att->calledtime + $TIME_OFFSET);
if ($sessndate===$calleddate) {
//$table->data[$i][] = ''.$calledtime.'
';
$table->data[$i][] = $calledtime;
}
else {
//$table->data[$i][] = ''.$calledtime.' ('.$calleddate.')
';
$table->data[$i][] = $calledtime.' ('.$calleddate.')';
}
}
//
$ipaddr = $att->ipaddress ? $att->ipaddress : get_string('novalue', 'autoattendmod');
if ($ipaddr) {
//$ipurl = jbxl_get_ipresolv_url($ipaddr);
$ipurl = autoattendmod_get_ipresolv_url($ipaddr);
if ($ipurl) $table->data[$i][] = "$ipaddr";
else $table->data[$i][] = $ipaddr;
}
else {
$table->data[$i][] = get_string('novalue', 'autoattendmod');
}
$table->data[$i][] = $att->remarks;
$i++;
}
}
echo '';
echo html_writer::table($table);
echo '
';
}
//
echo '';
echo '';
echo '';
echo '';
}
return;
}
//
// ダウンロード用のデータを作る
//
// $courseid: ダウンロードするコースのID
// $classes: 通常はクラス名(ID)の配列.中身があれば(内容は問わない),クラス名も表示する.
// $classid: ダウンロードするクラスのID.0なら全クラス.
// $viewmode: ダウンロードする期間.'all', 'weeks', 'months'
// $starttm: viewmode で,'weeks', 'months' を指定した場合の始まりの時刻指定.0なら現在.
// $attsid: ダウンロードするセッションのID.0 または 'all' なら全てのセッション.
// $students: 外部で表示する学生を定義する場合に指定する.データがある場合,つづく $sort,$order指定は無効になる.
// $sort: 'lastname', 'firstname', 'idnumber'
// $order: 'ASC', 'DESC'
function autoattendmod_make_download_data($courseid, $classes=null, $classid=0, $viewmode='all', $starttm=0, $attsid='all', $students=null, $sort='', $order='')
{
global $CFG, $DB, $TIME_OFFSET;
$settings = autoattendmod_get_grade_settings($courseid);
//
$indclass = '';
$indsess = '';
$indperiod = '';
if ($classid!=0) $indclass = ' AND (classid='.$classid.' OR classid=0)';
if ($viewmode!='all') {
if ($starttm==0) $starttm = time();
if ($viewmode==='weeks') {
$indperiod = " AND sessdate >= $starttm AND sessdate < ".($starttm + ONE_WEEK_TIME);
}
elseif ($viewmode==='months') {
$nxtmon = mktime(0, 0, 0, date('m', $starttm+$TIME_OFFSET)+1, 1, date('Y', $starttm+$TIME_OFFSET)) - $TIME_OFFSET;
$indperiod = " AND sessdate >= $starttm AND sessdate < ".$nxtmon;
}
}
if ($attsid!='all' and $attsid!=0) {
$indsess = ' AND id='.$attsid;
$viewmode = 'session';
}
// Only Closed Session
$qry = "SELECT * FROM {$CFG->prefix}autoattendmod_sessions where courseid=".$courseid.$indsess.$indclass.$indperiod.
" AND state='C' ORDER BY sessdate, starttime ASC";
$name_pattern = autoattendmod_get_namepattern($courseid);
//
$datas = new stdClass();
$datas->attr = array(); // 属性 'string', 'number'. デフォルトは 'string'
$datas->data = array();
$j = 0;
$k = 0;
$datas->attr[0] = array();
$datas->data[0] = array();
if ($CFG->fullnamedisplay=='lastname firstname') {
if ($name_pattern=='fullname' or $name_pattern=='lastname') {
$datas->attr[0][$k++] = '';
$datas->data[0][$j++] = get_string('lastname');
}
if ($name_pattern=='fullname' or $name_pattern=='firstname') {
$datas->attr[0][$k++] = '';
$datas->data[0][$j++] = get_string('firstname');
}
if ($sort=='') $sort = 'lastname';
}
else {
if ($name_pattern=='fullname' or $name_pattern=='firstname') {
$datas->attr[0][$k++] = '';
$datas->data[0][$j++] = get_string('firstname');
}
if ($name_pattern=='fullname' or $name_pattern=='lastname') {
$datas->attr[0][$k++] = '';
$datas->data[0][$j++] = get_string('lastname');
}
if ($sort=='') $sort = 'firstname';
}
//
if ($CFG->output_idnumber) {
$datas->attr[0][$k++] = '';
$datas->data[0][$j++] = 'ID';
}
if ($classes) {
$datas->attr[0][$k++] = '';
$datas->data[0][$j++] = get_string('classname', 'autoattendmod');
}
if ($viewmode=='session') {
$courseses = array();
if ($sess = $DB->get_records_sql($qry)) {
foreach($sess as $id=>$dsess) {
$date = strftime(get_string('strftimedmshort','autoattendmod'), $dsess->sessdate+$TIME_OFFSET);
$datas->attr[0][$k++] = '';
$datas->data[0][$j++] = $date;
$courseses[] = $dsess->id;
}
}
}
//
$datas->attr[0][$k++] = '';
$datas->attr[0][$k++] = '';
$datas->attr[0][$k++] = '';
$datas->attr[0][$k++] = '';
$datas->attr[0][$k++] = '';
$datas->attr[0][$k++] = '';
$datas->attr[0][$k++] = '';
//
$datas->data[0][$j++] = get_string('Cstatefull', 'autoattendmod');
$datas->data[0][$j++] = $settings['P']->title;
$datas->data[0][$j++] = $settings['X']->title;
$datas->data[0][$j++] = $settings['L']->title;
$datas->data[0][$j++] = $settings['E']->title;
$datas->data[0][$j++] = get_string('attendpercent','autoattendmod');
$datas->data[0][$j++] = get_string('attendgrade', 'autoattendmod');
if ($viewmode!='session') {
$courseses = array();
if ($sess = $DB->get_records_sql($qry)) {
foreach($sess as $id=>$dsess) {
$date = strftime(get_string('strftimedmshort','autoattendmod'), $dsess->sessdate+$TIME_OFFSET);
$datas->attr[0][$k++] = '';
$datas->data[0][$j++] = $date;
$courseses[] = $dsess->id;
}
}
}
//
if (!$students) {
$context = jbxl_get_course_context($courseid);
$students = autoattendmod_get_attend_students($courseid, $classid, $context, $sort, $order);
}
$i = 1;
foreach ($students as $student) {
$j = 0;
$k = 0;
$summary = autoattendmod_get_user_summary($student->id, $courseid);
$datas->data[$i] = array();
$datas->attr[$i] = array();
//
if ($CFG->fullnamedisplay == 'lastname firstname') {
if ($name_pattern=='fullname' or $name_pattern=='lastname') {
$datas->attr[$i][$k++] = '';
$datas->data[$i][$j++] = $student->lastname;
}
if ($name_pattern=='fullname' or $name_pattern=='firstname') {
$datas->attr[$i][$k++] = '';
$datas->data[$i][$j++] = $student->firstname;
}
}
else {
if ($name_pattern=='fullname' or $name_pattern=='firstname') {
$datas->attr[$i][$k++] = '';
$datas->data[$i][$j++] = $student->firstname;
}
if ($name_pattern=='fullname' or $name_pattern=='lastname') {
$datas->attr[$i][$k++] = '';
$datas->data[$i][$j++] = $student->lastname;
}
}
if ($CFG->output_idnumber) {
if (empty($student->idnumber)) $idnumber = '-';
else $idnumber = $student->idnumber;
$datas->attr[$i][$k++] = '';
$datas->data[$i][$j++] = $idnumber;
}
if ($classes) {
$datas->attr[$i][$k++] = '';
$datas->data[$i][$j++] = $summary['classname'];
}
if ($viewmode=='session') {
foreach ($courseses as $sid) {
if ($rec = $DB->get_record('autoattendmod_students', array('attsid'=>$sid, 'studentid'=>$student->id))) {
$datas->attr[$i][$k++] = '';
$datas->data[$i][$j++] = $settings[$rec->status]->acronym;
}
else {
$datas->attr[$i][$k++] = '';
$datas->data[$i][$j++] = '-';
}
}
}
//
$datas->attr[$i][$k++] = 'number';
$datas->attr[$i][$k++] = 'number';
$datas->attr[$i][$k++] = 'number';
$datas->attr[$i][$k++] = 'number';
$datas->attr[$i][$k++] = 'number';
$datas->attr[$i][$k++] = 'number';
$datas->attr[$i][$k++] = 'number';
//
$datas->data[$i][$j++] = $summary['complete'];
$datas->data[$i][$j++] = $summary['P'];
$datas->data[$i][$j++] = $summary['X'];
$datas->data[$i][$j++] = $summary['L'];
$datas->data[$i][$j++] = $summary['E'];
$datas->data[$i][$j++] = $summary['percent'];
$datas->data[$i][$j++] = $summary['grade'];
if ($viewmode!='session') {
foreach ($courseses as $sid) {
if ($rec = $DB->get_record('autoattendmod_students', array('attsid'=>$sid, 'studentid'=>$student->id))) {
$datas->attr[$i][$k++] = '';
$datas->data[$i][$j++] = $settings[$rec->status]->acronym;
}
else {
$datas->attr[$i][$k++] = '';
$datas->data[$i][$j++] = '-';
}
}
}
$i++;
}
return $datas;
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
// for Automatic Attendance
//
//
// 指定した条件で,現在出席をとっている授業の情報を返す.
//
// ex.) $sessions = autoattendmod_get_nowopen_sessions($courseid, $stdntid, 'S', $ntime);
//
function autoattendmod_get_nowopen_sessions($courseid, $stdntid, $method, $ntime)
{
$sesss = autoattendmod_get_unclosed_sessions($courseid, $method, $ntime, true);
$sessions = array();
foreach($sesss as $sess) {
if ($ntime>=$sess->starttime and $ntime<=$sess->endtime and $method==$sess->method) {
$sessions[] = $sess;
}
}
return $sessions;
}
//
// 指定した授業で,指定した評価を得たユーザ(複数)の情報を返す.
// $statuss は評価の配列(例:array('Y','P','X'))または評価の文字(例:'Y')
// または指定しない 指定しない場合は全ての評価を指定したことになる.
//
function autoattendmod_get_users_bystatus($sessid, $statuss='')
{
global $CFG, $DB;
//
$status = '';
if (is_array($statuss)) {
$substs = implode("' OR status='", $statuss);
if (!empty($substs)) $status = " AND ( status='".$substs."' )";
}
else {
if (!empty($statuss)) $status = " AND status='".$statuss."' ";
}
$qry = "SELECT * FROM {$CFG->prefix}autoattendmod_students WHERE attsid=".$sessid." ".$status." ORDER BY studentid ASC";
//print "QUERY = $qry
";
$return = array();
$users = $DB->get_records_sql($qry);
if ($users) {
foreach($users as $user) {
$return[$user->studentid] = new stdClass();
$return[$user->studentid]->id = $user->id;
$return[$user->studentid]->attsid = $user->attsid;
$return[$user->studentid]->studentid = $user->studentid;
$return[$user->studentid]->status = $user->status;
$return[$user->studentid]->called = $user->called;
$return[$user->studentid]->calledby = $user->calledby;
$return[$user->studentid]->calledtime = $user->calledtime;
$return[$user->studentid]->remarks = $user->remarks;
$return[$user->studentid]->ipaddress = $user->ipaddress;
}
}
return $return;
}
//
// 指定した授業での,指定したユーザの情報を返す.
//
/*
function autoattendmod_get_user_atsession($sessid, $userid)
{
global $CFG, $DB;
$qry = "SELECT * FROM {$CFG->prefix}autoattendmod_students WHERE attsid=".$sessid." AND studentid=".$userid;
//print "QUERY = $qry
";
$return = null;
$users = $DB->get_records_sql($qry);
if ($users) {
foreach ($users as $user) {
$return = new stdClass();
$return->id = $user->id;
$return->attsid = $user->attsid;
$return->studentid = $user->studentid;
$return->status = $user->status;
$return->called = $user->called;
$return->calledby = $user->calledby;
$return->calledtime = $user->calledtime;
$return->remarks = $user->remarks;
$return->ipaddress = $user->ipaddress;
break;
}
}
return $return;
}
*/
//
// まだクローズ状態にない授業の情報を返す..
// $methods はデフォルトの点呼方法の配列(例:array('A','S')または点呼方法の文字(例:'S')
// または指定なし.指定しない場合は全ての方法を指定したことになる.
// また,現在授業中ものも含めて返す場合は $incopen を true にする.
//
function autoattendmod_get_unclosed_sessions($courseid, $methods='', $ntime='', $incopen=false)
{
global $CFG, $DB;
$method = '';
if (is_array($methods)) {
$submth = implode("' OR method='", $methods);
if (!empty($submth)) $method = " AND ( method='".$submth."' )";
}
else {
if (!empty($methods)) $method = " AND method='".$methods."' ";
}
if (empty($ntime)) $ntime = time();
if ($incopen) $ctime = 'starttime';
else $ctime = 'endtime';
$qry = "SELECT * FROM {$CFG->prefix}autoattendmod_sessions ".
" WHERE courseid=".$courseid." AND state<>'C'".$method." AND (".$ctime.")<='".$ntime."' ".
" ORDER BY sessdate, starttime ASC";
//print "QUERY = $qry
";
$return = array();
$sesss = $DB->get_records_sql($qry);
if ($sesss) {
foreach($sesss as $sess) {
$return[$sess->id] = new stdClass();
$return[$sess->id]->id = $sess->id;
$return[$sess->id]->courseid = $sess->courseid;
$return[$sess->id]->classid = $sess->classid;
$return[$sess->id]->sessdate = $sess->sessdate;
$return[$sess->id]->starttime = $sess->starttime;
$return[$sess->id]->endtime = $sess->endtime;
$return[$sess->id]->latetime = $sess->latetime;
$return[$sess->id]->method = $sess->method;
$return[$sess->id]->attendkey = $sess->attendkey;
$return[$sess->id]->denysameip = $sess->denysameip;
$return[$sess->id]->allowip = $sess->allowip;
$return[$sess->id]->description = $sess->description;
$return[$sess->id]->state = $sess->state;
}
}
return $return;
}
//
// 学生用の授業用データレコードの追加
//
function autoattendmod_add_user_insession($sessid, $userid)
{
global $DB;
$rec = new stdClass();
$rec->attsid = $sessid;
$rec->studentid = $userid;
$rec->status = 'Y';
$rec->called = 'D';
$rec->calledby = 0;
$rec->calledtime = 0;
$rec->sentemail = 0;
$rec->remarks = '';
$rec->ipaddress = '';
$student = $DB->get_record('autoattendmod_students', array('attsid'=>$sessid, 'studentid'=>$userid));
if ($student) return $student;
//
$rec->id = $DB->insert_record('autoattendmod_students', $rec);
if ($rec->id) return $rec;
else return null;
}
//
// 指定されたセッションに対して,学生(複数)の登録状態を最新の状態に更新する.
// セッションデータを返す.
//
function autoattendmod_update_session_users($courseid, $sessid, $ntime='')
{
global $DB;
if ($sessid<=0) return null;
if (empty($ntime)) $ntime = time();
$sess = $DB->get_record('autoattendmod_sessions', array('id'=>$sessid));
if (!$sess) return null;
$context = jbxl_get_course_context($courseid);
$stdnts = jbxl_get_course_students($context);
if ($sess->state!='C' and $ntime>$sess->starttime) {
foreach($stdnts as $stdnt) {
$user = $DB->get_record('autoattendmod_students', array('attsid'=>$sess->id, 'studentid'=>$stdnt->id));
if (empty($user)) {
autoattendmod_add_user_insession($sess->id, $stdnt->id);
}
}
}
return $sess;
}
//
// 指定された授業(セッション)の点呼状態を最新の状態に更新する.
//
function autoattendmod_update_session_state($courseid, $sess, $ntime='', $regist=true)
{
global $DB;
if (!empty($sess)) {
$sess->prv_state = $sess->state;
//
if ($sess->state!='C') {
//
if (empty($ntime)) $ntime = time();
if ($ntime>$sess->endtime) {
$state = 'C';
}
else if ($ntime>=$sess->starttime and $ntime<=$sess->endtime) {
$state = 'O';
}
else {
$state = 'N';
}
if ($sess->state!=$state) {
$rec = new stdClass();
$rec->id = $sess->id;
$rec->state = $state;
$DB->update_record('autoattendmod_sessions', $rec);
unset($rec);
}
if ($regist) {
if ($sess->state!='O' and $state=='O') {
autoattendmod_update_session_users($courseid, $sess->id, $ntime); // 学生(複数)の授業レコードを登録
}
}
$sess->state = $state;
}
}
return $sess;
}
//
// コースの全授業(セッション)の点呼状態を最新の状態に更新する.
//
function autoattendmod_update_sessions_state($courseid, $sesss, $ntime='', $regist=true)
{
if (!empty($sesss) and is_array($sesss)) {
if (empty($ntime)) $ntime = time();
//
foreach($sesss as $key=>$sess) {
if ($sess->state!='C') {
$sesss[$key] = autoattendmod_update_session_state($courseid, $sesss[$key], $ntime, $regist);
}
else {
$sesss[$key]->prv_state = $sesss[$key]->state;
}
}
}
return $sesss;
}
/*
$sesss[$key]->prv_state = $sesss[$key]->state;
if ($ntime>$sess->endtime) {
if ($close) $state = 'C';
else $state = 'O'; // Close 処理しない
}
else if ($ntime>=$sess->starttime and $ntime<=$sess->endtime) {
$state = 'O';
}
else {
$state = 'N';
}
$rec = new stdClass();
$rec->id = $sess->id;
$rec->state = $state;
$DB->update_record('autoattendmod_sessions', $rec);
unset($rec);
$sesss[$key]->state = $state;
*/
//
// 指定されたセッションのデータを最新の状態に更新する
//
function autoattendmod_update_session($courseid, $sessid, $ntime='')
{
global $DB;
if ($sessid<=0) return null;
$sess = $DB->get_record('autoattendmod_sessions', array('id'=>$sessid));
if ($sess and $sess->state!='C') {
if (empty($ntime)) $ntime = time();
//
$sess = autoattendmod_update_session_state($courseid, $sess, $ntime); // 授業の状態を更新
if ($sess) {
if ($sess->method=='A') { // 自動処理
$logs = autoattendmod_get_courselogs($courseid, $sess->starttime, $sess->endtime);
autoattendmod_update_auto_session($courseid, $sess, $logs, $ntime);
}
if ($sess->state=='C') { // 授業で終了したものをクローズ
autoattendmod_close_session($courseid, $sess, $ntime);
// mail
if (autoattendmod_is_email_enable($courseid)) {
autoattendmod_email_teachers_attend($sess);
}
}
else if ($sess->prv_state!='O' and $sess->state=='O' and $sess->method=='S') {
if (autoattendmod_is_email_key($courseid)) {
autoattendmod_email_teachers_key($sess);
}
}
//
autoattendmod_update_grades_bycourseid($courseid);
return $sess;
}
}
return null;
}
//
// 指定されたコースの全てのデータを最新の状態に更新する
//
function autoattendmod_update_sessions($courseid, $ntime='')
{
if (empty($ntime)) $ntime = time();
$sesss = autoattendmod_get_unclosed_sessions($courseid, '', $ntime, true); // Open中を含む
$sesss = autoattendmod_update_sessions_state($courseid, $sesss, $ntime); // 授業の状態を更新
if ($sesss) {
$getlog = false;
$etime = 0;
$stime = $ntime;
foreach($sesss as $sess) {
if ($ntime>$sess->starttime and $sess->prv_state!='C') {
if ($stime>$sess->starttime) $stime = $sess->starttime;
if ($etime<$sess->endtime) $etime = $sess->endtime;
if ($sess->method=='A') $getlog = true;
}
}
if ($getlog) $logs = autoattendmod_get_courselogs($courseid, $stime, $etime);
else $logs = '';
//
foreach($sesss as $sess) {
if ($ntime>$sess->starttime and $sess->prv_state!='C') {
if ($sess->method=='A') { // 自動処理
autoattendmod_update_auto_session($courseid, $sess, $logs, $ntime);
}
if ($sess->state=='C') { // 授業で終了したものをクローズ
autoattendmod_close_session($courseid, $sess, $ntime);
// mail
if (autoattendmod_is_email_enable($courseid)) {
autoattendmod_email_teachers_attend($sess);
}
}
else if ($sess->prv_state!='O' and $sess->state=='O' and $sess->method=='S') {
if (autoattendmod_is_email_key($courseid)) {
autoattendmod_email_teachers_key($sess);
}
}
}
}
//
autoattendmod_update_grades_bycourseid($courseid);
return true;
}
return false;
}
//
// 自動モードの処理
//
function autoattendmod_update_auto_session($courseid, $sess, $logs, $ntime='')
{
global $DB;
$ver = jbxl_get_moodle_version();
$context = jbxl_get_course_context($courseid);
$users = jbxl_get_course_students($context);
if ($users) {
if (empty($ntime)) $ntime = time();
$attsid = $sess->id;
$stime = $sess->starttime;
$etime = $sess->endtime;
$ltime = $sess->latetime;
$allowip = $sess->allowip;
$difipf = $sess->denysameip;
$ipfmts = jbxl_to_subnetformats($allowip);
$used_ips = autoattendmod_get_usedips($attsid);
$sesslogs = array();
$is_email_user = autoattendmod_is_email_user($courseid);
if (!empty($logs)) {
foreach($logs as $log) {
if (floatval($ver)>=2.7) $logtime = $log->timecreated;
else $logtime = $log->time;
if ($logtime>=$stime and $logtime<=$etime) $sesslogs[] = $log;
}
}
foreach($users as $user) {
//
$status = 'X';
$match_ip = '';
$match_tm = 0;
$err_mesg = '';
$userlogs = array();
if (!empty($sesslogs)) {
foreach($sesslogs as $log) {
if ($log->userid==$user->id) $userlogs[] = $log;
}
}
$rec = new stdClass();
$rec->attsid = $sess->id;
$rec->studentid = $user->id;
$rec->status = 'Y';
$rec->called = 'A';
$rec->calledby = CALLED_BY_AUTO;
$rec->calledtime = $ntime;
$rec->sentemail = 0;
$rec->remarks = '';
$rec->ipaddress = '';
//
if (!empty($userlogs)) {
$valid_log = autoattendmod_check_valid_logip($userlogs, $ipfmts, $used_ips, $difipf);
if (!empty($valid_log)) {
if (isset($valid_log['ip'])) $match_ip = $valid_log['ip'];
if (isset($valid_log['time'])) $match_tm = $valid_log['time'];
if (isset($valid_log['error'])) $err_mesg = $valid_log['error'];
}
if (!empty($match_ip)) {
$status = 'P';
if ($difipf) $used_ips[] = $match_ip;
if ($ltime!=0) {
if ($match_tm > $stime + $ltime) $status = 'L';
}
$rec->ipaddress = $match_ip;
}
}
// ここで,$status は X, P, L のいずれか.
if ($status!='X') {
// $status は P か L
if ($match_tm!=0) $calledtime = $match_tm;
else $calledtime = $ntime;
$rec->status = $status;
$rec->sentemail = 0;
$sentemail = false;
$result = '';
$student = $DB->get_record('autoattendmod_students', array('attsid'=>$sess->id, 'studentid'=>$user->id));
if ($student and $student->status=='Y') {
$rec->id = $student->id;
$rec->calledtime = $calledtime;
$rec->sentemail = $student->sentemail;
$rec->remarks = $student->remarks;
if ($is_email_user and !$student->sentemail) {
$rec->sentemail = 1;
$sentemail = true;
}
$result = $DB->update_record('autoattendmod_students', $rec);
}
else if (empty($student)) {
if ($is_email_user) {
$rec->sentemail = 1;
$sentemail = true;
}
$result = $DB->insert_record('autoattendmod_students', $rec);
}
if ($result and $sentemail) autoattendmod_email_user($sess, $user, $status);
}
//
if ($err_mesg) {
$mdluser = $DB->get_record('user', array('id'=>$user->id));
//$loginfo = AUTO_SUBMIT_LOG.',id='.$sess->id.',userid='.$user->id.',user='.fullname($mdluser).',Error('.$err_mesg.')';
}
unset($rec);
}
}
}
//
// 授業のクローズ処理
//
function autoattendmod_close_session($courseid, $sess, $ntime='')
{
global $DB;
if ($sess->state=='C') {
//
$context = jbxl_get_course_context($courseid);
$users = jbxl_get_course_students($context);
// $users = autoattendmod_get_users_bystatus($sess->id, 'Y');
if ($users) {
if (empty($ntime)) $ntime = time();
//
$rec = new stdClass();
$rec->attsid = $sess->id;
$rec->status = 'X';
$rec->called = $sess->method;
$rec->calledby = 0;
$rec->calledtime = $ntime;
$rec->remarks = '';
$rec->ipaddress = '';
$is_email_user = autoattendmod_is_email_user($courseid);
foreach($users as $user) {
$rec->studentid = $user->id;
$rec->sentemail = 0;
$sentemail = false;
$result = '';
//
$student = $DB->get_record('autoattendmod_students', array('attsid'=>$sess->id, 'studentid'=>$user->id));
if (empty($student)) {
if ($is_email_user) {
$rec->sentemail = 1;
$sentemail = true;
}
$result = $DB->insert_record('autoattendmod_students', $rec);
}
else {
if ($student->status=='Y') {
$rec->id = $student->id;
$rec->sentemail = $student->sentemail;
if ($is_email_user and !$student->sentemail) {
$rec->sentemail = 1;
$sentemail = true;
}
$result = $DB->update_record('autoattendmod_students', $rec);
}
}
if ($result and $sentemail) autoattendmod_email_user($sess, $user, 'X');
}
//
unset($rec);
}
}
}
//
// 自動出欠モードでの学生の出欠を未了状態に戻す.
//
// 学生への通知メールのフラグはリセットしない
//
function autoattendmod_return_to_Y($sessid)
{
global $DB;
$students = $DB->get_records('autoattendmod_students', array('attsid'=>$sessid));
if ($students) {
foreach ($students as $student) {
if ($student->called=='A') {
$student->status = 'Y';
$student->ipaddress = '';
$student->calledbya = 0;
$DB->update_record('autoattendmod_students', $student);
}
}
}
return;
}
//
// logの中から許可されたフォーマット ipfmts に一致するIPを探す
// ただしdifipf が trueの場合,配列 userd_ipsに含まれるIPは一致から除外する.
//
function autoattendmod_check_valid_logip($userlogs, $ipfmts, $used_ips, $difipf)
{
$return = array();
if (empty($userlogs)) return $return;
$ver = jbxl_get_moodle_version();
$err_mesg = '';
foreach($userlogs as $log) {
$chkip = $log->ip;
if (empty($ipfmts) or jbxl_match_ipaddr($chkip, $ipfmts)) {
$chkip_f = true;
if ($difipf and !empty($used_ips)) {
foreach($used_ips as $used_ip) { // 同一IPチェック
if ($chkip==$used_ip) {
$chkip_f = false;
if (!empty($err_mesg)) $err_mesg.= ',';
$err_mesg.= 'already:'.$chkip;
break;
}
}
}
if ($chkip_f) {
$return['ip'] = $chkip;
if (floatval($ver)>=2.7) $return['time'] = $log->timecreated;
else $return['time'] = $log->time;
$return['userid'] = $log->userid;
return $return;
}
}
else {
if (!empty($err_mesg)) $err_mesg.= ',';
$err_mesg.= 'notmatch:'.$chkip;
}
}
if ($err_mesg) $return['error'] = $err_mesg;
return $return;
}
//
// 半自動モードに於いて接続IPの検査を行う.
//
function autoattendmod_check_invalid_semiautoip($att)
{
$ipaddr = getremoteaddr();
$allowip = $att->allowip;
$difipf = $att->denysameip;
$iperrmesg = '';
$ipfmts = jbxl_to_subnetformats($allowip);
if (empty($ipfmts) or jbxl_match_ipaddr($ipaddr, $ipfmts)) {
if ($difipf) {
$used_ips = autoattendmod_get_usedips($att->id);
if ($used_ips) {
foreach($used_ips as $used_ip) {
if ($ipaddr==$used_ip) {
$iperrmesg = get_string('sameusedip', 'autoattendmod').' '.$ipaddr;
break;
}
}
}
}
}
else {
$iperrmesg = get_string('mismatchip', 'autoattendmod').' '.$ipaddr;
}
return $iperrmesg;
}
//
// 既に取られた出席からIPを取り出す
//
function autoattendmod_get_usedips($attsid)
{
global $DB;
$results = $DB->get_records('autoattendmod_students', array('attsid'=>$attsid));
$ips = array();
foreach ($results as $result) {
$ips[] = $result->ipaddress;
}
return $ips;
}
//
// 指定したコースの $stime から $etime までのログを得る
//
function autoattendmod_get_courselogs($courseid, $stime, $etime=0)
{
global $CFG, $DB;
$return = array();
if ($etime<=0) {
$etime = time();
}
$ver = jbxl_get_moodle_version();
if (floatval($ver)>=2.7) {
$where = 'WHERE courseid='.$courseid;
$where.= ' AND timecreated>='.$stime.' AND timecreated<='.$etime;
$where.= " AND (action='viewed' OR action='review') ORDER BY timecreated ASC";
$qry = "SELECT * FROM {$CFG->prefix}logstore_standard_log ".$where;
}
else {
$where = 'WHERE course='.$courseid;
$where.= ' AND time>='.$stime.' AND time<='.$etime;
$where.= " AND (action='view' OR action='review') ORDER BY time ASC";
$qry = "SELECT * FROM {$CFG->prefix}log ".$where;
}
//print "QUERY = $qry
";
$logs = $DB->get_records_sql($qry);
return $logs;
}
/*
//
// 指定したコースの過去 $day日のログを得る
//
function autoattendmod_get_courselogs_pastdays($courseid, $day=0)
{
global $CFG, $DB;
$return = array();
$where = 'WHERE course='.$courseid;
if ($day>0) {
$lmtdy = time() - $day*ONE_DAY_TIME;
$where.= ' AND time>'.$lmtdy;
}
$where.= " AND (action='view' OR action='review') ORDER BY time ASC";
$qry = "SELECT * FROM {$CFG->prefix}log ".$where;
//print "QUERY = $qry
";
$logs = $DB->get_records_sql($qry);
return $logs;
}
*/
/////////////////////////////////////////////////////////////////////////////////////////////
//
//
function autoattendmod_get_ipresolv_url($ip)
{
global $CFG;
if (!preg_match('/(^\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/', $ip, $match)) return '';
if ($match[1]>255 or $match[2]>255 or $match[3]>255 or $match[4]>255) return '';
if ($match[1]=='127' or $match[1]=='10') return '';
if ($match[1]=='172' and $match[2]>='16' and $match[2]<='31') return '';
if ($match[1]=='192' and $match[2]=='168') return '';
if (!empty($CFG->ipresolv_url)) $url = sprintf($CFG->ipresolv_url, $ip);
else $url = sprintf(get_string('ipresolv_url','autoattendmod'), $ip);
return $url;
}