XE 시험 모듈의 포크 버전
develop 브랜치를 clone하시는것은 권장하지 않습니다. git clone으로 사용시 main 브랜치를 clone하시는것을 권장합니다.
XE 시험 모듈의 포크 버전
Home Page: https://yjsoft.xyz/exam_fork
License: GNU General Public License v2.0
재도전, 재응시 기능은 없나요? 아니면 틀린 것만 다시 풀기를 하면 좋을텐데...
from : https://www.xpressengine.com/index.php?mid=download&package_id=22753571&release_id=22754771
보셨는지 모르겠지만 이런 기능 요청이 있었는데요.
https://xetown.com/topics/1407214#comment_1407749
생각해보니 소제목 넣는 것 외에도 문제들간에 공통 지문이 쓰일 경우도 있을 것 같아서 요긴한 기능이라는 생각이 들었습니다.
현재 생각으로는 exam_question 테이블의 status 칼럼을 이용해서 문제 출제시에 소제목 또는 공통지문 형식으로 데이터를 등록해도 괜찮겠다는 소견입니다. 물론 자체 question_srl을 가지는 것으로요.
(한 가지 걸리는 것은 룰셋 검증을 거치는 것인데 js로 필수값을 대강 입력해주면 될 듯도 하구요.)
살펴보니 해당 테이블의 status 칼럼이 비밀 문제를 판별하는 변수로 보이는데요. 실제로는 사용하지 않는 기능이나 마찬가지더라구요. 공개/비밀로 노출을 결정하는 건 시험지 자체에서 처리하는 것으로 족할 것 같구요.
그래서 status 칼럼을 가지고 해당 기능을 추가해도 무방할지 의견 여쭙고자 합니다. 혹시라도 따로 복안이 있으시면 다른 방도를 구해봐야 할 것 같아서요.
현재 오류 메시지 출력이 이중적 체계로 이뤄져 있습니다.
exam.admin.model.php와 exam.controller.php에서는 makeObject 함수를 사용하고 있고,
exam.view.php에서는 dispExamMessage라는 별도의 함수를 통해 스킨의 message.html 템플릿 파일을 컴파일하도록 되어 있습니다.
예. https://dev.aporia.blog/exam_21235 에서 '응시' 버튼 눌렀을 때와 '시험지 생성' 버튼 눌렀을 때
사이트 전체적인 통일성을 위해 exam.view.php에서도 makeObject 함수를 사용하는 것이 더 좋을 것 같습니다.
그렇게 하면, 사이트 전체에 통일감을 줄 수 있고, 스킨 작업에서도 message.html 파일을 삭제함으로써 스킨의 체계를 간소화하고 작업량도 줄일 수 있을 것 같습니다.
조금더 친화적으로 바꾸면 어떨런지 모르겠습니다.
비공개 점수 공개 풀이 공개 전체 공개
시험 응시 후 결과를 어떻게 알려줄 것인지 선택할 수 있습니다. 비공개를 설정하면 응시자는 결과를 확인할 수 없으며 전체 공개로 설정하시면 정답까지 보여줍니다.
: 솔직히 채점결과를 알려주지 않는 경우가 있어야 하는지 이해가 잘 안됩니다. 시험지 결과는 확인이 언제나 가능 해야 할듯 합니다.
exam.controller.php 파일
#245행
$args->description_title = htmlspecialchars($params->description_title, ENT_COMPAT | ENT_HTML401, 'UTF-8', false);
에서처럼 파라미터값이 잘못 코드화되어 있었습니다.
$args->description_title = htmlspecialchars($params->q_description_title, ENT_COMPAT | ENT_HTML401, 'UTF-8', false);
으로 고쳤더니 DB에 입력도 잘 되고 스킨 상에서도 잘 출력됩니다.
근데 이거 그냥 $args->description_title = escape($params->q_description_title); 으로 간소화해도 되지 않나요? 아... XE에선 안 되던가요;;;
휴면계정 모듈이 별도 저장 회원목록이 삭제되지 않는 현상이 발생하여
모든 모듈을 지우고 테스트 해서 확인 결과
시험 모듈 삭제 후 테스트 할 경우 정상적으로 작동하지만
시험 모듈을 재 설치 하고 삭제할 경우 에러 표기 후 삭제 되지 않습니다.
'시험 응시 현황'(act=disExamMyResult)을 보면 합격/불합격 리스트만 따로 가져올 수 있도록 search_status를 파라미터로 넘겨줍니다.
(기존 스킨에서는 이걸 검색폼 형태로 넘겨주고 있는데ㅜㅜ 그냥 getUrl() 함수에 쿼리를 넘겨주는 링크 작업으로 대체 중입니다)
다만, 라이믹스 1.9.9.6 디벨롭 버전(2020-04-27) 기준으로 리스트 선별 취득에 실패하고 있었습니다.
disExamMyResult 함수(463행)에 있는 $args->status = Context::get('search_status'); 에서는 값이 잘 전달되고 있었는데요.
문제는 $args를 받고 있는 exam.model.php의 getExamResultList() 함수더군요.
여기 함수를 보면 lang.xml에서 $statusList 변수를 가져와서 파라미터값을 검증해서 잘못된 값이면 unset 시키는 부분이 있는데, $statusList가 ArrayObject여서인지 private이 걸려 있어서인지 array_key_exists 함수가 아예 안 먹히고 있었습니다.
즉, 353행 if(!array_key_exists(strtoupper($obj->status),$statusList)) unset($obj->status); 에서 무조건 false만 반환해서 status 값이 사라집니다.
그래서 이 부분을
if ( !isset($statusList[strtoupper($obj->status)]) ) unset($obj->status);
으로 수정했더니 status에 해당하는 search_status 파라미터가 잘 전달이 되어 스킨에서도 무사히 출력되는 것을 확인할 수 있었습니다.
exam.item.php에서 총 배점이 0일 경우 100으로 출력하도록 되어 있습니다.
각 문제에 배점이 하나도 배정되어 있지 않거나, total_point 계산에 실패했을 경우에 0점이 됩니다.
이것을 굳이 100점으로 표시할 이유는 없어 보입니다.
뿐만 아니라 경우에 따라 100점 만점이 아닌 경우도 있기 때문에 100점으로 고정하는 것은 더욱 더 필요가 없어보입니다.
exam.item.php 566행
return $this->get('total_point') == 0 ? 100 : $this->get('total_point');
대신에
return $this->get('total_point');
으로 바로 출력값을 가져오는 것이 타당해보입니다.
라이믹스 2.0.0 이상 버전에서 시험응시 현황 삭제가 되지 않는 버그가 있습니다.
1.9.9 까지에 버전에서는 테스트 시 정상 작동합니다.
Object
-> BaseObject
최신버전에서 편집 저장후 이렇게 떠요??
You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '?,
question_type
= ?,title
= ?,content
= ?,answer
= ?,answer1
= ?,' at line 1
from : https://www.xpressengine.com/index.php?mid=download&package_id=22753571&release_id=22754771
현재 미확인 상태
라이믹스의 '짧은 주소' > '모든 주소 형태를 사용' 옵션을 사용하면
Context::get('document_srl')을 인식하지 못해 시험지가 열리지 않는 문제가 있습니다.
module.xml 22행을 다음과 같이 바꿔서 이 문제에 대응할 수 있었습니다.
<action name="dispExamIndex" type="view" index="true">
<route route="$document_srl:int" priority="100" />
</action>
단, XE나 라이믹스 2.x 미만에서는 테스트해보지 못했습니다.
어쨌든 라이믹스의 라우터 기능에 대응해서 해당 파일의 소스를 일부 업데이트하는 것이 필요하다고 생각합니다.
현재 본업으로 매우 바쁜 상태라... 9월 말쯤 일정이 정리되는대로 작업 재개 예정입니다.
현재는 시험 문제를 삭제할 때 해당 문제의 배점(point)만큼 시험의 총배점(total_point)이 감소되지 않고 있습니다.
procExamQuestionDelete() 함수를 개선할 필요가 있겠습니다.
exam.controller.php #328-329 행의
$output = $this->deleteQuestion($args);
if(!$output->toBool()) return $output;
윗부분을 다음과 같이 바꾸니 total_point도 수정되고 캐시 삭제로 바뀐 값도 바로 적용됩니다.
$output = $this->deleteQuestion($args);
if(!$output->toBool()) return $this->makeObject(-1, "msg_invalid_request");
// 삭제한 문제의 배점만큼 만점 재계산
$total_point = $examitem->get('total_point') - $questionitem->get('point');
$output = $this->updateTotalPoint($document_srl, $total_point);
if(!$output->toBool()) return $this->makeObject(-1, "Failed to update total_point");
//remove from cache
$oCacheHandler = CacheHandler::getInstance('object');
if($oCacheHandler->isSupport())
{
//remove document item from cache
$cache_key = 'exam_item:'. getNumberingPath($document_srl) . $document_srl;
$oCacheHandler->delete($cache_key);
}
문제 출제 및 수정 시에 exec_json으로 기존의 시험문제를 불러올 수 있는 기능을 고안해봤습니다.
기본적으로는 1-1) 작동 중인 모듈의 모듈번호 기준으로 문제를 가져오고, 1-2) 모듈번호 인자를 전달하지 않으면 모든 시험문제를 리스트로 가져와서, 2) 문제를 선택한 뒤 출제 및 수정 폼 필드들에 덮어쓰는 방식입니다.
다음과 같이 액션, 함수, 쿼리를 추가해봤습니다.
살펴봐주셨으면 합니다~
module.xml 에 액션 추가
<action name="getQuestions" type="model" />
exam.model.php 에 함수 추가
/**
* 모듈 내의 모든 문제를 구함
* @param int $module_srl
* @return object
*/
function getQuestions($module_srl = 0, $status = 'Y')
{
// get a list of questions
$args = new stdClass;
$args->module_srl = $module_srl ? $module_srl : Context::get('module_srl');
if ( !Context::get('grant')->manager ) $args->status = $status ? $status : Context::get('status');
$output = executeQueryArray('exam.getQuestions', $args);
// return if an error occurs in the query results
if ( !$output->toBool() ) return;
$this->add('question_list', $output->data);
return $output->data;
}
<query id="getQuestions" action="select">
<tables>
<table name="exam_question" alias="question" />
<table name="exam" alias="exam" />
</tables>
<columns>
<column name="question.*" />
<column name="exam.title" alias="document_title" />
<query id="getCategoryTitle" alias="category_title">
<tables>
<table name="document_categories" alias="category" />
</tables>
<columns>
<column name="category.title" />
</columns>
<conditions>
<condition operation="equal" column="category.category_srl" default="exam.category_srl" />
</conditions>
</query>
</columns>
<conditions>
<condition operation="equal" column="question.module_srl" var="module_srl" filter="number" pipe="and" />
<condition operation="equal" column="exam.document_srl" var="question.document_srl" notnull="notnull" pipe="and" />
<condition operation="equal" column="question.status" var="status" pipe="and" />
</conditions>
<navigation>
<index var="question.list_order" default="question.list_order" order="ASC" />
</navigation>
</query>
https://xetown.com/questions/1544625
라이믹스는 XE에서 업그레이드한 경우가 아니라면 내부적으로 UTC
시간대를 사용
시간 입력시 DB에 저장될 때 별도로 변환작업을 해주지 않으면 UTC
기준 적용되어 추후 불러올시 시간이 잘못 출력될 수 있음
시간 만료전 페이지를 닫고 다시 열어 시간제한을 회피하는것을 방지
객관식 문제를 출제하거나 수정할 때 번호를 클릭하면 원형문자가 붉은색으로 변하고 해당번호는 정답으로 지정됩니다.
이때 이벤트 처리에서 e.preventDefault()를 추가해줘서 클릭시 스크롤이 document 최상단으로 움직이는 것을 방지해야 합니다.
./modules/exam/tpl/js/exam_admin.js 30행에 해당 구문을 추가하는 것이 좋겠습니다.
e.preventDefault();
빈 시험지에 문제를 새로 출제할 경우 총 배점으로 가산되지 않는 문제가 있습니다.
총 배점을 문제 리스트를 루프 돌려서 각 문제별로 point를 누적 가산시켜서 total_point를 구해오는데,
문제 리스트가 부재하는 경우에는 total_point의 초기값인 0이 그대로 반영되기 때문으로 이해됩니다.
exam.controller.php #276-281행이 이렇게 되어 있는데요.
$total_point = 0;
$question_list = $oExamModel->getQuestionList($document_srl);
foreach($question_list->data as $key => $val)
{
$total_point += $val->point;
}
다음과 같이 바꿀 것을 제안합니다.
$total_point = 0;
$question_list = $oExamModel->getQuestionList($document_srl);
if ( count($question_list) )
{
foreach($question_list->data as $key => $val)
{
$total_point += $val->point;
}
}
else
{
$total_point += $args->point;
}
서술형 문제 등 정답을 정해두기 애매한 경우 출제자가 직접 확인후 채점할수 있도록 구현
이외 객관식의 경우도 상황에 따라 정답처리할수 있도록 구현
시험지가 추천을 받으면 포인트를 얻고, 비추천을 받으면 포인트를 잃음
시험지 추천/비추천으로 얻을수 있는 포인트 제한 구현
exam.controller.php 파일 수정 필요
// 객관식이고 복수정답일때 처리
if(!$qitem->getQType() && $q_answer_count>1)
{
$answer_list = explode(",", $answer);
$q_answer_list = $qitem->getAnswerList();
$answer_check_type = $qitem->get('answer_check_type');
// 모두일치하면 정답+부분점수(기본배점/맞은갯수)
if($answer_check_type==2)
{
$cnt = 0;
foreach($answer_list as $key => $val)
{
if(in_array($val, $q_answer_list))
{
$cnt++;
}else{
$cnt = 0;
break;
}
}
if($cnt) {
if($cnt==$q_answer_count) $check = 'O';
else $check = 'P';
}
} elseif($answer_check_type==1) // 모두일치하면 정답
{
$cnt = 0;
foreach($answer_list as $key => $val)
{
if(in_array($val, $q_answer_list))
{
$cnt++;
}else{
$cnt= 0 ;
break;
}
}
if($cnt==$q_answer_count) $check = 'O';
} else { // 하나만 일치해도 정답.
foreach($answer_list as $key => $val)
{
if(!in_array($val, $q_answer_list))
{
$check = 'X';
break;
}else{
$check = 'O';
}
}
}
} else { // 복수 정답이 아닐때..
라이믹스 업데이트로 레이아웃 CSS가 에디터에 삽입되며 발생한 부작용으로 수정 필요
배점이 100점이 아닐수 있게 됨에 따라 제한을 두는건 더이상 무의미함
출제자는 시험지 업데이트는 가능한 반면에
응시자는 시험을 1번 치루고 나서는 시험지가 업데이트되더라도 일괄 재응시가 불가능합니다.
가장 좋은건 변경된 문제로만 재 응시 하여 전체 채점 결과가 변동이 되는 것일 것 같습니다.
의견 적어 봅니다.
감사합니다.
즉, 출제자가 누구인지 알수 있어야 할듯 합니다.
중요한 기능 중에 하나가 시험지의 출제 문제 순서 변경이라고 생각합니다.
그래서 스킨에서 문제의 순서를 바꾸려고 시도를 해봤는데,
인접한 두 문제의 question_srl과 list_order를 놔두고 나머지 칼럼 데이터를 바꿔치기 하는 것말고는 별다른 방도가 없을 것 같습니다.
게시판 모듈의 확장변수처럼 document_srl을 공유하는 문항들에 idx를 별도 칼럼으로 두는 것도 좋겠지만, 그 또한 스키마 변경 및 그에 따르는 작업량이 만만치 않을 것 같더라구요ㅜ
그래서 문제의 순서를 변경할 수 있는 exam.controller.php에 별도의 함수를 작성하고 module.xml에도 관련 액션을 추가해서, 스킨단에서 exec_json으로 해당 기능을 구현해봤습니다.
exam.controller.php의 354행쯤부터...
/**
* @brief 시험지에 문제 순서 변경 처리
*/
public function procExamQuestionSwap()
{
// 권한 체크
if ( $this->module_info->module !== 'exam' ) return $this->makeObject(-1, 'msg_invalid_request');
if ( !$this->grant->create ) return $this->makeObject(-1, 'msg_not_permitted');
$oExamModel = getModel('exam');
// 선택된 문제 번호로 php 변수에 데이터 담아두기
$selected_srl = Context::get('selected_srl');
$selected_item = $oExamModel->getQuestion($selected_srl);
// 표적화된 문제번호로 php 변수에 데이터 담아두기
$targeted_srl = Context::get('targeted_srl');
$targeted_item = $oExamModel->getQuestion($targeted_srl);
// 선택 문제에 표적 문제의 데이터를 이전
$args = new StdClass;
$args->question_srl = $selected_srl;
$args->question_level = $targeted_item->get('question_level');
$args->question_type = $targeted_item->get('question_type');
$args->title = $targeted_item->get('title');
$args->content = $targeted_item->get('content');
$args->answer = $targeted_item->get('answer');
for ( $i = 1; $i <= 5; $i++ )
{
$args->{'answer'.$i} = $targeted_item->get('answer'.$i);
}
$args->answer_check_type = $targeted_item->get('answer_check_type');
$args->use_description = $targeted_item->get('use_description');
$args->description_title = $targeted_item->get('description_title');
$args->description = $targeted_item->get('description');
$args->regdate = $targeted_item->get('regdate');
$args->ipaddress = $targeted_item->get('ipaddress');
$args->status = $targeted_item->get('status');
$args->point = $targeted_item->get('point');
$output = $this->updateQuestion($args);
// 표적 문제에 선택 문제의 데이터를 이전
$args = new StdClass;
$args->question_srl = $targeted_srl;
$args->question_level = $selected_item->get('question_level');
$args->question_type = $selected_item->get('question_type');
$args->title = $selected_item->get('title');
$args->content = $selected_item->get('content');
$args->answer = $selected_item->get('answer');
for ( $i = 1; $i <= 5; $i++ )
{
$args->{'answer'.$i} = $selected_item->get('answer'.$i);
}
$args->answer_check_type = $selected_item->get('answer_check_type');
$args->use_description = $selected_item->get('use_description');
$args->description_title = $selected_item->get('description_title');
$args->description = $selected_item->get('description');
$args->regdate = $selected_item->get('regdate');
$args->ipaddress = $selected_item->get('ipaddress');
$args->status = $selected_item->get('status');
$args->point = $selected_item->get('point');
$output = $this->updateQuestion($args);
}
그리고 module.xml의 35행쯤에
<action name="procExamQuestionSwap" type="controller" />
등을 추가했습니다.
문항 순서 변경을 위해 급하게 짜긴 했는데요.
일단 스킨단에서 무리없이 받아서 순서를 변경하는 데에는 성공할 수 있었습니다.
메뉴 새글 모듈과 연동이 될런지는 모르겠지만 가능하다면 메뉴에도 N/U 아이콘이 붙으면 좋겠습니다.
https://xetown.com/index.php?&mid=rxe_point&search_keyword=새글&search_target=title_content&document_srl=12592
늘 감사합니다.
기능상 영향은 없는 것 같은데요. 그래도 라이믹스에서 에러메시지 출력이 눈에 밟혀서ㅜ 제보 및 수정 상황 공유합니다.
모듈 설정 화면(dispExamAdminInsert)에서 디버그 패널을 참고했습니다...
exam.controller.php #26행
$extra_vars[$key] = new ExtraItem($module_srl, -1, in_array($key,'user_name','nick_name') ? Context::getLang('exam_writer') . " " . Context::getLang($key) : Context::getLang($key), $key, 'N', 'N', 'N', null);
=> $extra_vars[$key] = new ExtraItem($module_srl, -1, in_array($key, array('user_name','nick_name')) ? Context::getLang('exam_writer') . " " . Context::getLang($key) : Context::getLang($key), $key, 'N', 'N', 'N', null);
으로 수정했습니다.
tpl/exam_insert.html #233행
<input type="checkbox" name="exam_pass_group_list[]" value="{$key}" id="group_{$key}" checked="checked"|cond="in_array($key,$module_info->exam_pass_group_list)" />
=> <input type="checkbox" name="exam_pass_group_list[]" value="{$key}" id="group_{$key}" checked="checked"|cond="is_array($module_info->exam_pass_group_list) && in_array($key,$module_info->exam_pass_group_list)" />
으로 수정했습니다.
마찬가지 시험지 생성시에
포인트 차감이 가능하도록 하고 더 나아가 표시도 가능하면 동기부여에 좋을듯 합니다.
감사합니다.
온라인으로 하는 시험이다보니 볼때마다 문제순서가 바꾸는 기능이 있으면 좋겠네요.
최고 관리자는 시험응시현황을 볼 수 있으나
모듈 관리자는 권한이 없습니다.
모듈 관리자도 취지상 확인이 가능해야 하지 않을까 싶습니다.
자꾸 올려서 죄송합니다. 바쁘실 텐데ㅜㅜ
스킨 작업을 하다보니까 눈에 들어오는 것들이 있어서요.
현재 스킨에서 '시험기간'은 exam.item.php 355행의 getExamDate($format = 'Y.m.d H:i') 함수를 받아서 출력하는 걸로 되어 있는데요.
이 부분이 너무 깁니다.
2020.05.15 12:00 ~ 2020.05.15 13:00 이런 식으로요.
이용자 입장에서는 시험지 목록에서 시험기간이 표시항목으로 있을 경우 기간 식별이 어렵고 시각적 피로감마저 느낄 수 있습니다.
그래서 이 부분을 2020.05.15 12시 ~ 13시 같은 식으로 줄여서 출력하면 어떨까 하는 생각이 들었습니다.
시작일시와 종료일시의 문자열을 비교해서 중복되는 형식을 생략해서
날짜 표기를 간소화하도록 getExamDate() 함수를 아래와 같이 수정하면 어떨까 합니다.
function getExamDate()
{
if ( !$this->isDate() )
{
$str = Context::getLang('exam_no_end_date');
}
else
{
$start_date = $this->get('start_date');
$end_date = $this->get('end_date');
// 조건 설정 : 시작과 종료의 년도가 현재 년도와 같은지
$this_year = substr($start_date, 0, 4) === date('Y') && substr($end_date, 0, 4) === date('Y');
// 시작과 종료 모두 H시 정각이라면
if ( substr($start_date, 10, 2) === '00' && substr($end_date, 10, 2) === '00' )
{
// 시작 시각은 시까지만 출력
$startline = $this_year ? zdate($start_date, 'm.d H시'): zdate($start_date, 'Y.m.d H시');
$str = $startline . ' ~ ';
// 시작과 종료가 같은 시각이라면
if ( substr($start_date, 0, 10) === substr($end_date, 0, 10) ) $str = $startline;
// 일자까지 같다면
elseif ( substr($start_date, 0, 8) === substr($end_date, 0, 8) ) $str .= zdate($end_date, 'H시');
// 년도만 같다면
else if ( substr($startline, 0, 4) === substr($end_date, 0, 4) ) $str .= zdate($end_date, 'm.d H시');
// 년도가 다르다면
else $str .= $this_year ? zdate($end_date, 'm.d. H시') : zdate($end_date, 'Y.m.d. H시');
}
else
{
// 시작 시각은 분까지 출력
$startline = $this_year ? zdate($start_date, 'm.d H시i분'): zdate($start_date, 'Y.m.d H시i분');
$str = $startline . ' ~ ';
// 시작과 종료가 같은 시각이라면
if ( substr($start_date, 0, 12) === substr($end_date, 0, 12) ) $str = $startline;
// 시까지 같다면
elseif ( substr($start_date, 0, 10) === substr($end_date, 0, 10) ) $str .= zdate($end_date, 'i분');
// 일자까지 같다면
elseif ( substr($start_date, 0, 8) === substr($end_date, 0, 8) ) $str .= zdate($end_date, 'H시i분');
// 년도만 같다면
else if ( substr($startline, 0, 4) === substr($end_date, 0, 4) ) $str .= zdate($end_date, 'm.d H시i분');
// 년도가 다르다면
else $str .= $this_year ? zdate($end_date, 'm.d H시i분'): zdate($end_date, 'Y.m.d H시i분');
}
}
return $str;
}
시작시간과 종료시간을 입력하려면 달력과 시간 위젯이 뜨는데요.
이 위젯에서는 시간 단위만 입력되고 분 단위를 입력할 수가 없습니다.
이 부분에 대한 개선이 필요해보입니다.
수동으로 배점을 한 이후
시험지 설정을 변경할 경우 배점 설정이 초기화 됨.
스킨에서 create.html 파일에 아래와 같이 exam_total_point 값 추가 필요
input type="hidden" name="exam_total_point" id="exam_total_point" value="{($examitem->get('total_point'))? $examitem->get('total_point') : '0'}" maxlength="3"
시험지 설정 화면(act=dispExamCreate)에서
시작시간의 초단위가 자동입력되는 현상이 있습니다.
해당 설정을 초기화해서 시작시간을 재입력하면 00초 단위로 잘 입력되지만,
설정을 수정하기 위해 들어가면 value값 초단위에 현재시각의 초가 자동 반영됩니다.
시험지 설정을 '등록'라고 나면 start_date 값에 해당 초값이 저장되게 되구요.
입력할 때 아예 초단위를 제거하는 것이 차라리 나을 것 같습니다.
계속 비공개로 고정됨
DB 수동 변경시 정상작동함
현재 시험지나 시험지 리스트 변수에는 카테고리 번호가 제공되고 있습니다만,
채점 결과($resultitem) 및 채점 결과 리스트($result_list) 변수에는 카테고리 번호가 누락되어 있습니다.
확인해보니 각각 getResult와 getResultList 쿼리에서 exam 테이블에서 title과 result_type 칼럼을 가져오고 있는데요.
각각의 쿼리 xml에서 칼럼에
<column name="exam.category_srl" />
를 추가해서 채점 결과 및 리스트 변수에서도 시험 카테고리를 가져오면 좋겠습니다.
그렇게 하면 시험 응시 현황 페이지 및 채점 결과 팝업 창 등에서도 시험의 분류 제목을 출력하는 것이 용이해질 수 있겠습니다.
현재 시험모듈에서 위지윅 에디터는 시험문제 출제 및 수정 화면에서 로드됩니다.
시험모듈에서 에디터 설정은 스킨 지정 외에는 별다른 옵션이 없는 상태입니다.
물론 모듈 내에서 다양한 에디터 설정 옵션을 두는 것도 좋겠지만, 현실적으로 모듈 내에서 에디터 활용이 잦은 것도 아니어서 그보다는 간소한 방법을 선택하는 것이 더 나을 것 같습니다.
그래서 exam.view.php 파일의 dispExamEditMode 함수에서 에디터 로드를 할 때,
설정을 수동 지정해서 로드하는 getEditor 함수보다는,
아예 에디터 모듈로부터 getModuleEditor 함수를 가져오는 게 더 나아보입니다.
그런 맥락에서 421행부터 에디터를 가져오는 부분을 아래와 같이 하는 것이 어떨까 합니다.
// 지문에서 사용할 에디터 로드 $oEditorModel = getModel('editor'); $editor = $oEditorModel->getModuleEditor('exam', $this->module_srl, $question_srl, 'question_srl', 'q_description_content'); Context::set('editor', $editor);
이렇게 하면 (특히 라이믹스의 모바일 ck에디터의 경우에는) 좀 더 효과적인 툴바를 가져오는 이점도 챙길 수 있을 것으로 기대됩니다.
채점 결과 링크 주소에 오타가 있어서
채점 결과 팝업창이 지정된 스킨이 아니라 기본 스킨으로만 열리는 문제가 있습니다.
tpl/result_list.html 60행의
$module_info->mid->mid 를 $module_info->mid 으로 바꿔야겠습니다~
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.