From bef7cac25e4f1d12816b2af2da5d27414757354c Mon Sep 17 00:00:00 2001
From: = <=>
Date: Tue, 25 Jul 2017 03:36:57 +0800
Subject: [PATCH 1/5] for PR
---
.gitignore | 5 +-
config.php | 17 +-
config.sample.php | 71 +++++
data/edusystem.sql | 146 ++++++++++
extensions/controllers/BaseController.php | 104 +++++--
extensions/controllers/ProxyController.php | 261 +++++++++++++++---
libs/AmsProxy/AmsProxy.php | 71 ++++-
libs/AmsProxy/curl.php | 7 +-
libs/AmsProxy/functions/__base__.php | 23 +-
libs/AmsProxy/functions/getArchivesEx.php | 20 +-
libs/AmsProxy/functions/getClassSchedule.php | 61 ++++
libs/AmsProxy/functions/getGPA.php | 55 ++++
libs/AmsProxy/functions/getRankExamForm.php | 41 ++-
libs/AmsProxy/functions/getScore.php | 250 ++++++++++-------
libs/AmsProxy/functions/getScoreAffirm.php | 15 +-
libs/AmsProxy/functions/getScoreMinor.php | 36 +++
libs/AmsProxy/functions/getValidScore.php | 60 ++++
libs/AmsProxy/functions/getValidScoreImg.php | 47 ++++
libs/AmsProxy/functions/noneCourse.jpg | Bin 0 -> 18340 bytes
libs/AmsProxy/functions/noneCourse_.jpg | Bin 0 -> 100959 bytes
libs/AmsProxy/functions/noneScore.jpg | Bin 0 -> 9698 bytes
libs/AmsProxy/functions/noneScore_.jpg | Bin 0 -> 8433 bytes
.../yii/gii/controllers/DefaultController.php | 2 +-
models/Common.php | 6 +
models/ims_jiaowu.php | 6 +
.../admin/controllers/FeedbackController.php | 2 +-
modules/admin/controllers/HomeController.php | 2 +-
modules/admin/controllers/StatsController.php | 8 +-
modules/admin/views/feedback/index.tpl | 2 +-
modules/admin/views/home/index.tpl | 6 +-
modules/admin/views/layouts/main.tpl | 6 +-
modules/admin/views/student/index.tpl | 2 +-
modules/proxy/controllers/ApiController.php | 2 +-
.../proxy/controllers/CourseController.php | 22 ++
modules/proxy/controllers/HomeController.php | 41 ++-
.../proxy/controllers/PersonalController.php | 3 +
.../proxy/controllers/RankExamController.php | 21 +-
modules/proxy/controllers/ScoreController.php | 131 +++++----
.../proxy/controllers/SettingController.php | 11 +-
modules/proxy/views/common/login.css | 3 +
modules/proxy/views/common/login.tpl | 24 +-
modules/proxy/views/common/stats.tpl | 14 +-
modules/proxy/views/common/table.tpl | 11 +
modules/proxy/views/course/tableImg.tpl | 8 +
modules/proxy/views/home/about.tpl | 5 +
modules/proxy/views/home/feedback.tpl | 9 +-
modules/proxy/views/home/index.tpl | 66 ++---
modules/proxy/views/layouts/main.tpl | 115 ++++----
modules/proxy/views/score/GPA.tpl | 16 ++
modules/proxy/views/score/score.tpl | 16 ++
modules/proxy/views/score/stats_.js | 107 +++++++
modules/proxy/views/score/table.tpl | 4 +-
modules/proxy/views/score/validScore.tpl | 16 ++
modules/proxy/views/setting/update.tpl | 6 +
public/css/bootstrap.min.css | 2 +-
public/css/common.css | 2 +-
public/css/proxy.css | 2 +-
public/index.php | 2 +
src/less/common.less | 4 +-
59 files changed, 1587 insertions(+), 408 deletions(-)
create mode 100644 config.sample.php
create mode 100644 data/edusystem.sql
create mode 100644 libs/AmsProxy/functions/getClassSchedule.php
create mode 100644 libs/AmsProxy/functions/getGPA.php
create mode 100644 libs/AmsProxy/functions/getScoreMinor.php
create mode 100644 libs/AmsProxy/functions/getValidScore.php
create mode 100644 libs/AmsProxy/functions/getValidScoreImg.php
create mode 100644 libs/AmsProxy/functions/noneCourse.jpg
create mode 100644 libs/AmsProxy/functions/noneCourse_.jpg
create mode 100644 libs/AmsProxy/functions/noneScore.jpg
create mode 100644 libs/AmsProxy/functions/noneScore_.jpg
create mode 100644 models/Common.php
create mode 100644 models/ims_jiaowu.php
create mode 100644 modules/proxy/views/common/login.css
create mode 100644 modules/proxy/views/course/tableImg.tpl
create mode 100644 modules/proxy/views/home/about.tpl
create mode 100644 modules/proxy/views/score/GPA.tpl
create mode 100644 modules/proxy/views/score/score.tpl
create mode 100644 modules/proxy/views/score/stats_.js
create mode 100644 modules/proxy/views/score/validScore.tpl
diff --git a/.gitignore b/.gitignore
index 5c67d54..4d3b378 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,8 +1,9 @@
/public/adminer.php
/public/phpinfo.php
/data/amsProxy.db
-/runtime/cache
-/runtime/views
+/runtime
+/public/img/captcha
+/public/img/cache
*.swp
.idea
/bower_components
diff --git a/config.php b/config.php
index 4a0d93c..45187c1 100644
--- a/config.php
+++ b/config.php
@@ -21,7 +21,12 @@
),
'components' => array(
'db' => array(
- 'connectionString' => 'sqlite:../data/amsProxy.db',
+ // 'connectionString' => 'sqlite:../data/amsProxy.db',
+ 'class'=>'CDbConnection',
+ 'connectionString'=>'mysql:host=localhost;dbname=eduSystem',
+ 'username'=>'root',
+ 'password'=>'sDA6kFbInOrtELb6lEI6!',
+ 'emulatePrepare'=>true, // needed by some MySQL installations
),
'viewRenderer' => array(
'class' => 'ext.view.CPradoViewRenderer',
@@ -31,7 +36,8 @@
'urlFormat' => 'path',
'showScriptName' => false,
'rules' => array(
- '' => 'site/home/index',
+ '' => 'proxy/',
+ // '' => 'site/home/index',
'about' => 'site/home/about',
'faq' => 'site/home/faq',
'wechat' => 'site/wechat/index',
@@ -52,11 +58,14 @@
),
'params' => array(
'debug' => true,
- 'baseUrl' => 'http://ams.gxun.edu.cn/',
- 'schoolcode' => '10608',
+ 'curl_debug' => true,
+ 'useCaptcha'=>true,
+ 'baseUrl' => 'http://119.146.68.54/Jwweb/',
+ 'schoolcode' => '10577',
'superAdmin' => array(
'110263100136',
'111253050122',
+ '1514080902121'
),
),
);
diff --git a/config.sample.php b/config.sample.php
new file mode 100644
index 0000000..20fd2a3
--- /dev/null
+++ b/config.sample.php
@@ -0,0 +1,71 @@
+ '..',
+ 'modules' => array(
+ 'admin' => array(
+ 'defaultController' => 'home',
+ ),
+ 'proxy' => array(
+ 'defaultController' => 'home',
+ ),
+ 'site' => array(
+ 'defaultController' => 'home',
+ ),
+ 'wechat',
+ ),
+ 'defaultController' => 'site',
+ 'import' => array(
+ 'ext.controllers.*',
+ 'application.libs.AmsProxy.AmsProxy',
+ 'application.models.*',
+ ),
+ 'components' => array(
+ 'db' => array(
+ // 'connectionString' => 'sqlite:../data/amsProxy.db',
+ 'class'=>'CDbConnection',
+ 'connectionString'=>'',
+ 'username'=>'',
+ 'password'=>'',
+ 'emulatePrepare'=>true,
+ ),
+ 'viewRenderer' => array(
+ 'class' => 'ext.view.CPradoViewRenderer',
+ 'fileExtension' => '.tpl',
+ ),
+ 'urlManager' => array(
+ 'urlFormat' => 'path',
+ 'showScriptName' => false,
+ 'rules' => array(
+ '' => 'proxy/',
+ // '' => 'site/home/index',
+ 'about' => 'site/home/about',
+ 'faq' => 'site/home/faq',
+ 'wechat' => 'site/wechat/index',
+
+ 'proxy/login' => 'proxy/home/login',
+
+ 'api' => 'site/home/api',
+ 'api/vcode' => 'site/api/vcode',
+ 'api/login' => 'site/api/login',
+ 'api/logout' => 'site/api/logout',
+ 'api/courses' => 'proxy/api/courses',
+ 'api/scores' => 'proxy/api/scores',
+ 'api/rankExam' => 'proxy/api/rankExam',
+ 'api/archives' => 'proxy/api/archives',
+ 'api/exam' => 'proxy/api/exam',
+ ),
+ ),
+ ),
+ 'params' => array(
+ 'debug' => true,
+ 'curl_debug' => true,
+ 'useCaptcha'=>true,
+ 'baseUrl' => '',
+ 'schoolcode' => '10577',
+ 'superAdmin' => array(
+ '110263100136',
+ '111253050122',
+ '1514080902121'
+ ),
+ ),
+);
diff --git a/data/edusystem.sql b/data/edusystem.sql
new file mode 100644
index 0000000..1f887f7
--- /dev/null
+++ b/data/edusystem.sql
@@ -0,0 +1,146 @@
+-- phpMyAdmin SQL Dump
+-- version 4.6.5.2
+-- https://www.phpmyadmin.net/
+--
+-- Host: localhost
+-- Generation Time: 2017-01-19 06:53:57
+-- 服务器版本: 5.7.13
+-- PHP Version: 5.6.22
+
+SET SQL_MODE = "NO_AUTO_VALUE_ON_ZERO";
+SET time_zone = "+00:00";
+
+
+/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
+/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
+/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
+/*!40101 SET NAMES utf8mb4 */;
+
+--
+-- Database: `edusystem`
+--
+
+-- --------------------------------------------------------
+
+--
+-- 表的结构 `common`
+--
+
+CREATE TABLE `common` (
+ `id` varchar(10) NOT NULL,
+ `rankExamForm` text
+) ENGINE=InnoDB DEFAULT CHARSET=utf8;
+
+
+-- --------------------------------------------------------
+
+--
+-- 表的结构 `message`
+--
+
+CREATE TABLE `message` (
+ `id` int(11) NOT NULL,
+ `sender` text NOT NULL,
+ `receiver` text NOT NULL,
+ `message` text NOT NULL,
+ `time` decimal(10,0) NOT NULL,
+ `state` int(11) NOT NULL DEFAULT '0'
+) ENGINE=InnoDB DEFAULT CHARSET=utf8;
+
+-- --------------------------------------------------------
+
+--
+-- 表的结构 `setting`
+--
+
+CREATE TABLE `setting` (
+ `start_date` date NOT NULL,
+ `end_date` date NOT NULL,
+ `wechat_auto_reply` int(11) NOT NULL,
+ `wechat_token` text NOT NULL
+) ENGINE=InnoDB DEFAULT CHARSET=utf8;
+
+--
+-- 转存表中的数据 `setting`
+--
+
+INSERT INTO `setting` (`start_date`, `end_date`, `wechat_auto_reply`, `wechat_token`) VALUES
+('2017-02-16', '2017-07-02', 1, 'you-token');
+
+-- --------------------------------------------------------
+
+--
+-- 表的结构 `student`
+--
+
+CREATE TABLE `student` (
+ `sid` varchar(20) NOT NULL,
+ `pwd` varchar(20) DEFAULT NULL,
+ `archives` text,
+ `course` text,
+ `scoreAffirm` text,
+ `validScore` text,
+ `rank_exam` text,
+ `exam_arrangement` text,
+ `theory_subject` text,
+ `last_login_time` date DEFAULT NULL,
+ `openid_subscribe` text,
+ `openid_server` text,
+ `is_admin` int(11) DEFAULT NULL
+) ENGINE=InnoDB DEFAULT CHARSET=utf8;
+
+--
+-- 表的结构 `wechat_log`
+--
+
+CREATE TABLE `wechat_log` (
+ `id` int(11) NOT NULL,
+ `message` text NOT NULL,
+ `state` int(11) NOT NULL DEFAULT '0'
+) ENGINE=InnoDB DEFAULT CHARSET=utf8;
+
+--
+-- Indexes for dumped tables
+--
+
+--
+-- Indexes for table `common`
+--
+ALTER TABLE `common`
+ ADD PRIMARY KEY (`id`);
+
+--
+-- Indexes for table `message`
+--
+ALTER TABLE `message`
+ ADD PRIMARY KEY (`id`);
+
+--
+-- Indexes for table `student`
+--
+ALTER TABLE `student`
+ ADD PRIMARY KEY (`sid`);
+
+--
+-- Indexes for table `wechat_log`
+--
+ALTER TABLE `wechat_log`
+ ADD PRIMARY KEY (`id`);
+
+--
+-- 在导出的表使用AUTO_INCREMENT
+--
+
+--
+-- 使用表AUTO_INCREMENT `message`
+--
+ALTER TABLE `message`
+ MODIFY `id` int(11) NOT NULL AUTO_INCREMENT;
+--
+-- 使用表AUTO_INCREMENT `wechat_log`
+--
+ALTER TABLE `wechat_log`
+ MODIFY `id` int(11) NOT NULL AUTO_INCREMENT;
+/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
+/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
+/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
diff --git a/extensions/controllers/BaseController.php b/extensions/controllers/BaseController.php
index bd6fba5..e8a39f5 100644
--- a/extensions/controllers/BaseController.php
+++ b/extensions/controllers/BaseController.php
@@ -54,36 +54,80 @@ public function init() {
/**
* @return string error message
*/
- public function login($sid, $pwd, $captcha) {
- if ($error = $this->AmsProxy()->login($sid, $pwd, $captcha)) {
- return $error;
- } else {
- $this->saveStudent();
- $this->updateStudentLastLoginTime(
- Student::model()->findByPk($sid));
- $_SESSION['session'] = $this->AmsProxy()->getSession();
- $_SESSION['student'] = array(
- 'sid' => $sid,
- 'pwd' => $pwd,
- 'isAdmin' => $this->isAdmin($sid),
- );
+ public function login($sid, $pwd, $captcha=null, $force=false) {
+ $student = Student::model()->findByPk($sid);
+
+ if( ($captcha == null|| $captcha == '') && isset($student->sid) && $pwd == $student->pwd && !$force){
+ $this->afterLogin($sid,$pwd,false);
+ }elseif($captcha){
+ if ($error = $this->AmsProxy()->login($sid, $pwd, $captcha)) {
+ return $error;
+ } else {
+ $this->afterLogin($sid,$pwd,true);
+ }
+ }else{
+ $count = 0;
+ $url = 'public/img/captcha/'.$sid.'.jpg';
+ $url = dirname(__FILE__).'/../../'.$url;
+ do{
+ $check = file_put_contents($url,$this->AmsProxy()->getCaptcha());
+ $ch = curl_init();
+ curl_setopt($ch, CURLOPT_URL, $this->AmsProxy()->orcApi.'http://proxy.deepkolos.cn/img/captcha/'.$sid.'.jpg?t='.time());
+ curl_setopt($ch, CURLOPT_HEADER, 0);
+ curl_setopt($ch, CURLOPT_USERAGENT, "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0)");
+ curl_setopt($ch, CURLOPT_RETURNTRANSFER,1);
+ curl_setopt($ch, CURLOPT_TIMEOUT, "3");//单位为秒
+ curl_setopt($ch,CURLOPT_FOLLOWLOCATION,true); //完成重定向
+ // curl_setopt($ch,CURLOPT_PROXY,'127.0.0.1:8887');//设置代理服务器
+ // curl_setopt($ch,CURLOPT_SSL_VERIFYPEER,0);//若PHP编译时不带openssl则需要此行
+ $captcha = curl_exec($ch);
+ curl_close($ch);
+
+ // $error = $captcha;
+ if(strlen($captcha) == 4)
+ if($error = $this->AmsProxy()->login($sid, $pwd, $captcha)){
+ ;
+ }else{
+ $this->afterLogin($sid,$pwd,true);
+ }
+ else{
+ $error = '验证码错误!';
+ // echo '收到的验证码长度为:'.$captcha.'
';
+ }
+ $count++;
+ }while($error == '验证码错误!' && $count < 5);
+ // unlink($url);
+ if($error != null)
+ return $error;
}
}
-
/**
* @return bool
*/
public function isLogged() {
return isset($_SESSION['student']);
}
-
- public function saveStudent() {
- if (Student::model()->findByPk($this->AmsProxy()->sid) == null) {
+ public function afterLogin($sid,$pwd,$setSession){
+ $this->saveStudent($sid,$pwd);
+ $this->updateStudentLastLoginTime(
+ Student::model()->findByPk($sid));
+ if($setSession)
+ $_SESSION['session'] = $this->AmsProxy()->getSession();
+ $_SESSION['student'] = array(
+ 'sid' => $sid,
+ 'pwd' => $pwd,
+ 'isAdmin' => $this->isAdmin($sid),
+ );
+ }
+ public function saveStudent($sid,$pwd) {
+ $student = Student::model()->findByPk($sid);
+ if (!$student) {
$student = new Student;
- $student->sid = $this->AmsProxy()->sid;
- $student->archives = json_encode($this->get_archives());
- $student->save();
}
+ $student->sid = $sid;
+ $student->pwd = $pwd;
+ // $student->archives = json_encode($this->get_archives());
+ $student->save();
}
/**
@@ -120,7 +164,8 @@ public function AmsProxy() {
}
else {
$this->amsProxy = new AmsProxy;
- $_SESSION['session'] = $this->amsProxy->getSession();
+ if($this->amsProxy->getSession())
+ $_SESSION['session'] = $this->amsProxy->getSession();
}
}
@@ -228,12 +273,15 @@ public function information($message) {
*/
public function weekNumber($date=null) {
if ($date)
- $time = strtotime($date);
+ $now = strtotime($date);
else
- $time = time();
-
- $time -= strtotime($this->setting['start_date']);
- return (int)($time / 86400 / 7 + 1);
+ $now = time();
+ $start = strtotime($this->setting['start_date']);
+ $week_offset = (int)date('N',$start) - 1;
+ $start_ajusted = $start - $week_offset * 86400;
+ $day = ($now - $start_ajusted)/86400;
+ $week = floor($day/7);
+ return $week;
}
/**
@@ -244,6 +292,10 @@ public function createFullUrl($route, $params=array(), $ampersand='&') {
$route, $params, $ampersand);
}
+ public function noneNull(&$obj){
+ return (isset($obj))?$obj:null;
+ }//我觉得应该这个使用宏比较好吧
+
/**
* get request param with get or post
*
diff --git a/extensions/controllers/ProxyController.php b/extensions/controllers/ProxyController.php
index c34a2a4..baed11c 100644
--- a/extensions/controllers/ProxyController.php
+++ b/extensions/controllers/ProxyController.php
@@ -1,33 +1,88 @@
isLogged())
$this->notLoggedHandler();
+
+ global $config;
+ if($config['params']['useCaptcha']){
+ if(isset($_GET['refreshed']))
+ if(!$this->AmsProxy()->testCurl()){
+ $lastsid = $_SESSION['student']['sid'];
+ $lastpwd = $_SESSION['student']['pwd'];
+
+ $_SESSION = array();
+ session_destroy();
+ session_start();
+
+ $this->AmsProxy()->curl->cookies['ASP.NET_SessionId'] = null;
+ unset($this->AmsProxy()->curl->cookies['ASP.NET_SessionId']);
+ $_SESSION['session'] = $this->AmsProxy()->getSession();
+ $this->AmsProxy()->setSession($_SESSION['session']);
+
+ $this->notLoggedHandler($lastsid,$lastpwd,'更新数据需要登陆一下下~');
+ }
+
+ if(isset($_GET['referer'])){
+ $this->redirect(urldecode($_GET['referer']).'?refreshed=true');
+ }
+ }
$this->student = Student::model()->findByPk(
$_SESSION['student']['sid']);
+ if(!$this->common = Common::model()->findByPk('common')){
+ $this->common = new Common;
+ $this->common->id = 'common';
+ $this->common->save();
+ }
+
$this->unread = $this->getUnreadMessage();
- $this->update();
+
+ $this->update(array(
+ 'fields'=>array('archives'),
+ 'fileFields'=>array(),
+ 'commonFields'=>array(),
+ 'force'=>false
+ ));
}
public function checkSession() {
@@ -37,30 +92,58 @@ public function checkSession() {
} else {
setcookie(
'session', $this->AmsProxy()->getSession(),
- time() + 4 * 365 * 24 * 60 * 60, '/');
+ time() + 3 * 356 * 60 * 60, '/');
}
}
}
- public function notLoggedHandler() {
+ public function notLoggedHandler($lastsid='', $lastpwd='',$message=null) {
+ // setcookie('sessionchanged','true',time()+3600*24); // 现在改为一天
+ // if(isset($_SESSION['lastLoginId']) && isset($_SESSION['lastLoginPw'])){
+ // $sid = $_SESSION['lastLoginId'];
+ // $pwd = $_SESSION['lastLoginPw'];
+ // if($student = Student::model()->findByPk($sid))
+ // if ($error = $this->login($sid, $pwd)) {
+ // $this->render('/common/login', array(
+ // 'error' => $error,
+ // 'sid' => $sid,
+ // 'pwd' => $pwd,
+ // 'captcha' => '',
+ // ));
+
+ // Yii::app()->end();
+ // }
+ // }
+ global $config;
+
if ($_SERVER['REQUEST_METHOD'] == "POST") {
$sid = $_POST['sid'];
$pwd = $_POST['pwd'];
-
- if ($error = $this->login($sid, $pwd, $_POST['captcha'])) {
+ $captcha = (isset($_POST['captcha'])) ? $_POST['captcha'] : null;
+ if ($error = $this->login($sid, $pwd, $captcha)) {
+ $captchaImg = ($config['params']['useCaptcha'])?base64_encode($this->AmsProxy()->getCaptcha()):'';
+ //其实如果第一次自动识别验证码失败时候直接转为人工输入好了
$this->render('/common/login', array(
'error' => $error,
'sid' => $sid,
- 'captcha' => base64_encode(
- $this->AmsProxy()->getCaptcha())
+ 'pwd' => $pwd,
+ 'captcha' => $captchaImg,
+ 'message' => $message
));
Yii::app()->end();
}
+ $_SESSION['lastLoginId'] = $sid;
+ $_SESSION['lastLoginPw'] = $pwd;
} else {
+ $captchaImg = ($config['params']['useCaptcha']) ? base64_encode($this->AmsProxy()->getCaptcha()) : '';
+ // $sid = (isset($_SESSION['lastLoginId'])) ? $_SESSION['lastLoginId'] : '';
+ // $pwd = (isset($_SESSION['lastLoginPw'])) ? $_SESSION['lastLoginPw'] : '';
$this->render('/common/login', array(
- 'captcha' => base64_encode(
- $this->AmsProxy()->getCaptcha())
+ 'sid' => $lastsid,
+ 'pwd' => $lastpwd,
+ 'captcha' => $captchaImg,
+ 'message' => $message
));
Yii::app()->end();
@@ -83,19 +166,39 @@ public function get_archives() {
$this->AmsProxy()->invoke('getArchivesEx')
);
}
+ public function get_rankExamForm() {
+ return $this->AmsProxy()->invoke('getRankExamForm');
+ }
/**
* @return array
*/
public function get_score() {
- return array(
- // $this->AmsProxy()->invoke('getScore', 0),
- // $this->AmsProxy()->invoke('getScore', 1),
- $this->AmsProxy()->invoke(
- 'getScoreAffirm', $this->get('archives')->{'入学年份'}),
- );
+ return $this->AmsProxy()->invoke('getScore');
}
-
+ public function get_scoreMinor() {
+ return $this->AmsProxy()->invoke('getScoreMinor');
+ }
+ public function get_GPA() {
+ return $this->AmsProxy()->invoke('getGPA');
+ }
+ public function get_scoreAffirm() {
+ //获取行政班级
+ // $archives = $this->get('archives');
+ // $startYear = '20'.substr($archives->{'行政班级'},0,2);
+ $startYear = '20'.substr($_SESSION['student']['sid'],0,2);//还是从学号提取吧
+ return $this->AmsProxy()->invoke('getScoreAffirm',$startYear);
+ }
+ public function get_validScore() {
+ return $this->AmsProxy()->invoke('getValidScore');
+ }
+ public function get_validScoreImg() {
+ return $this->AmsProxy()->invoke('getValidScoreImg');
+ }
+ public function get_classSchedule() {
+ return $this->AmsProxy()->invoke('getClassSchedule');
+ }
+
/**
* @return array
*/
@@ -114,7 +217,6 @@ public function get_rank_exam() {
'score' => $this->AmsProxy()->invoke('getRankExamScore'),
);
}
-
/**
* @return array
*/
@@ -122,39 +224,126 @@ public function get_theory_subject() {
return $this->AmsProxy()->invoke('getTheorySubject');
}
- /**
- * @return array
- */
public function get_exam_arrangement() {
return $this->AmsProxy()->invoke('getExamArrangement');
}
- /**
- * @param bool $force
- */
- public function update($force=false) {
- foreach ($this->fields as $field)
- if ($force || !$this->student->{$field})
- $this->updateItem($field);
+ public function update($config) {
+ if(is_array($config)){
+ $config = (object)$config;
+ $force = $this->noneNULL($config->force);
+ $fields = $this->noneNULL($config->fields);
+ $fileFields = $this->noneNULL($config->fileFields);
+ $commonFields = $this->noneNULL($config->commonFields);
+ $this->updateItem('fields',$fields,$force);
+ $this->updateItem('fileFields',$fileFields,$force);
+ $this->updateItem('commonFields',$commonFields,$force);
+ }
+ }
+ public function updateItem($func,$fields,$force){
+ if(is_array($fields))
+ foreach ($fields as $field){
+ if ($force || !$this->{'checkCache_'.$func}($field)){
+ $this->getAuthToUpdate();
+ $this->{'update_'.$func}($field);
+ }
+ }
}
-
/**
* @param string $field
*/
- public function updateItem($field) {
+ public function update_fields($field) {
$this->student->{$field} = json_encode($this->{'get_' . $field}());
$this->student->save();
}
+ public function update_commonFields($field) {
+ $this->common->{$field} = json_encode($this->{'get_' . $field}());
+ $this->common->save();
+ }
+ public function update_fileFields($field) {
+ return file_put_contents($this->cacheUrl($field),$this->{'get_' . $field}());
+ }
+ public function checkCache_fileFields($field){
+ return file_exists($this->cacheUrl($field));
+ }
+ public function checkCache_fields($field){
+ return $this->student->{$field};
+ }
+ public function checkCache_commonFields($field){
+ return $this->common->{$field};
+ }
+
+ public function getCache($field){
+ if(file_exists($this->cacheUrl($field)))
+ return file_get_contents($this->cacheUrl($field));
+ return '';
+ }
+ public function cacheUrl($field){
+ return CACHE.$field.'/_hidden_'.$_SESSION['student']['sid'].'.jpg';
+ }
+ public function webUrl($field){
+ return 'img/cache/'.$field.'/_hidden_'.$_SESSION['student']['sid'].'.jpg';
+ }
+ public function getAuthToUpdate(){
+ if(!$this->AmsProxy()->testCurl()){
+ global $config;
+ // echo '还没有获取到获取权限~';
+ $this->AmsProxy()->curl->cookies['ASP.NET_SessionId'] = null;
+ unset($this->AmsProxy()->curl->cookies['ASP.NET_SessionId']);
+ $_SESSION['session'] = $this->AmsProxy()->getSession();
+ $this->AmsProxy()->setSession($_SESSION['session']);
+
+ if($config['params']['useCaptcha']){
+ $this->redirect('/?refreshed=true&referer='.urlencode($_SERVER['HTTP_REFERER']));
+ die();
+ }
+
+ $error = $this->login($this->student->sid, $this->student->pwd, null,true);
+ if($error){
+ $this->warning('验证码自动识别失败了: '.$error.'~');
+ Yii::app()->end();
+ }
+ return true;
+ }
+ // echo '以获取到权限了';
+ return true;
+ }
/**
* @param string $field
* @param bool $json_encode
* @return mixed
*/
- public function get($field, $json_encode=true) {
- if ($json_encode)
+ public function get($field, $type='fields') {//分类就会牵动很多的变化了,要么就通过数字含义进行路由
+ //还是单独检查是否更新吧
+ if ($type == 'fields')
return json_decode($this->student->{$field});
- else
- return $this->student->{$field};
+ elseif($type == 'fileFields')//文件类,读取原数据
+ return $this->getCache($field);
+ elseif($type == 'commonFields'){
+ return json_decode($this->common->{$field});
+ }
+ }
+ public function getXNXQ() {
+ return $this->getXN() . $this->getXQ();
+ }
+ public function getXN() {
+ $month = (int) date('m');
+ $year = (int) date('Y');
+ $day = (int) date('d');
+ if ($month < 7)
+ $year -= 1;
+ return $year;
+ }
+ public function getXQ() {
+ $month = (int) date('m');
+ $day = (int) date('d');
+ return ( $month <= 2 || ($month >= 6) ) ? '0' : '1';
+ }
+ public function lastXN(){
+ return (!$this->lastXQ())? $this->getXN() : $this->getXN() -1;
+ }
+ public function lastXQ(){
+ return ($this->getXQ()) ? 0 : 1 ;
}
}
diff --git a/libs/AmsProxy/AmsProxy.php b/libs/AmsProxy/AmsProxy.php
index 2af7eca..e3218de 100644
--- a/libs/AmsProxy/AmsProxy.php
+++ b/libs/AmsProxy/AmsProxy.php
@@ -28,6 +28,9 @@ class AmsProxy {
*/
public $schoolcode;
+ public $isTestOk = false;
+
+ public $orcApi = 'http://meanchun.com/wb/wbocr/wbocr.php?url=';
/**
* @param string $session
@@ -37,8 +40,8 @@ public function __construct($session=null) {
$this->curl->setTimeout(4);
$this->baseUrl = Yii::app()->params['baseUrl'];
$this->schoolcode = Yii::app()->params['schoolcode'];
- $session = $session ? $session : $this->generateSessionId();
- $this->setSession($session);
+ if($session != null)
+ $this->setSession($session);
}
/**
@@ -65,7 +68,7 @@ public function login($sid, $pwd, $captcha) {
preg_match(
'/color:Red;">(.*?)', $responseText, $matches);
if (isset($matches[1])) {
- return $matches[1];
+ return $matches[1];//这里输出验证码错误还有密码错误信息
} else {
return '系统错误,无法登录';
}
@@ -73,7 +76,29 @@ public function login($sid, $pwd, $captcha) {
$this->sid = $sid;
}
}
-
+
+ public function testCurl(){//还有就是会多次测试,其实只要每个updateget一次权限就可以了
+ // var_dump($this->isTestOk);
+ if(!$this->isTestOk){
+ $month = (int) date('m');
+ $year = (int) date('Y');
+ if ($month <= 7)
+ $year -= 1;
+ $result = $this->POST(
+ 'xscj/c_ydcjrdjl_rpt.aspx',
+ array(
+ 'sel_xnxq' => $year.($month < 3 || $month > 7 ? '0' : '1'),
+ 'radCx' => 1,
+ 'btn_search' => '%BC%EC%CB%F7'
+ )
+ );
+ // echo "
{$result}"; + if(strpos($result, '系统提示:您无权访问此页') !== false || $result == ''){ + return false; + } + } + return $this->isTestOk = true; + } /** * _login 旧版登陆接口 * @return string error message @@ -104,6 +129,9 @@ public function _login($sid, $pwd) { public function GET($url, $params=null, $referer=null) { return $this->request('get', $url, $params, null, $referer); } + public function GETRaw($url, $params=null, $referer=null) { + return $this->requestRaw('get', $url, $params, null, $referer); + } /** * @param string $url @@ -115,7 +143,6 @@ public function GET($url, $params=null, $referer=null) { public function POST($url, $data, $params=null, $referer=null) { return $this->request('post', $url, $params, $data, $referer); } - /** * @param string $method * @param string $url @@ -146,13 +173,34 @@ public function request( ); } + public function requestRaw( + $method, $url, $params=null, $data=null, $referer=null) { + + if (!$referer) + $referer = $this->baseUrl . $url; + + return $this->curl->request( + array( + 'method' => $method, + 'url' => $this->baseUrl . $url, + 'params' => $params, + 'data' => $data, + 'headers' => array( + 'Referer' => $referer, + ), + ) + )->body; + } /** * @return string */ public function getSession() { - if (!isset($this->curl->cookies['ASP.NET_SessionId'])) - $this->GET(''); - + if (!isset($this->curl->cookies['ASP.NET_SessionId'])){ + $this->GET('_data/LOGIN_NEW.ASPX'); + if (!isset($this->curl->cookies['ASP.NET_SessionId'])){ + return $this->generateSessionId(); + } + } return $this->curl->cookies['ASP.NET_SessionId']; } @@ -164,6 +212,9 @@ public function getCaptcha() { array( 'method' => 'get', 'url' => $this->baseUrl . 'sys/ValidateCode.aspx', + 'headers' => array( + 'Referer' => $this->baseUrl . '_data/home_login.aspx ', + ), ) )->body; } @@ -179,8 +230,8 @@ public function setSession($session) { * @param string $function * @param mixed $args */ - public function invoke($functionName, $args=null) { - if (!class_exists($functionName, false)) + public function invoke($functionName, $args=null) {//应该设置__call方法的使用起来是更加自然 + if (!class_exists($functionName, false))//好像我有比原作更方便的加载方法哦~ include 'functions/' . $functionName . '.php'; $function = new $functionName($this, $args); diff --git a/libs/AmsProxy/curl.php b/libs/AmsProxy/curl.php index 649f053..d83c4b5 100644 --- a/libs/AmsProxy/curl.php +++ b/libs/AmsProxy/curl.php @@ -5,7 +5,7 @@ class curl_request { * @var array */ public $cookies = array(); - + public $curl = null; /** * @var array */ @@ -17,6 +17,11 @@ public function __construct() { $this->curl = curl_init(); curl_setopt($this->curl, CURLOPT_RETURNTRANSFER, true); curl_setopt($this->curl, CURLOPT_HEADER, true); + // + if(CURL_DEBUG){ + curl_setopt($this->curl,CURLOPT_PROXY,'127.0.0.1:8887');//设置代理服务器 + curl_setopt($this->curl,CURLOPT_SSL_VERIFYPEER,0);//若PHP编译时不带openssl则需要此行 + } } /** diff --git a/libs/AmsProxy/functions/__base__.php b/libs/AmsProxy/functions/__base__.php index c3b8c20..9e59076 100644 --- a/libs/AmsProxy/functions/__base__.php +++ b/libs/AmsProxy/functions/__base__.php @@ -21,7 +21,7 @@ public function __construct($amsProxy, $args) { public function run() { $data = $this->getData(); if ($data !== false) - return $this->parse($this->createDom($data)); + return $this->parse($this->createDom($data),$data); else return array(); } @@ -67,7 +67,7 @@ public function getData() {} * @param mixed $data * @return array */ - public function parse($data) {} + //public function parse($data,$raw) {} /** * 2015.1 ~ 2015.2 @@ -79,10 +79,25 @@ public function parse($data) {} * @return string */ public function getXNXQ() { + return $this->getXN() . $this->getXQ(); + } + public function getXN() { $month = (int) date('m'); $year = (int) date('Y'); - if ($month <= 7) + $day = (int) date('d'); + if ($month < 7) $year -= 1; - return $year . ($month < 3 || $month > 7 ? '0' : '1'); + return $year; + } + public function getXQ() { + $month = (int) date('m'); + $day = (int) date('d'); + return ( $month <= 2 || ($month >= 6) ) ? '0' : '1'; + } + public function lastXN(){ + return (!$this->lastXQ())? $this->getXN() : $this->getXN() -1; + } + public function lastXQ(){ + return ($this->getXQ()) ? 0 : 1 ; } } diff --git a/libs/AmsProxy/functions/getArchivesEx.php b/libs/AmsProxy/functions/getArchivesEx.php index 195687c..216e73b 100644 --- a/libs/AmsProxy/functions/getArchivesEx.php +++ b/libs/AmsProxy/functions/getArchivesEx.php @@ -34,11 +34,19 @@ public function getFromOther() { $this->amsProxy->GET('xsxj/Stu_xszcxs_rpt.aspx') )->getElementsByTagName('tr'); - $tds = $trs->item($trs->length - 1)->getElementsByTagName('td'); - return array( - '院(系)/部' => $tds->item(2)->textContent, - '年级/专业' => $tds->item(3)->textContent, - '行政班级' => $tds->item(4)->textContent, - ); + if($trs->item($trs->length - 1) != null){ + $tds = $trs->item($trs->length - 1)->getElementsByTagName('td'); + return array( + '院(系)/部' => $tds->item(2)->textContent, + '年级/专业' => $tds->item(3)->textContent, + '行政班级' => $tds->item(4)->textContent, + ); + }else{ + return array( + '院(系)/部' => '', + '年级/专业' => '', + '行政班级' => '', + ); + } } } diff --git a/libs/AmsProxy/functions/getClassSchedule.php b/libs/AmsProxy/functions/getClassSchedule.php new file mode 100644 index 0000000..46a888c --- /dev/null +++ b/libs/AmsProxy/functions/getClassSchedule.php @@ -0,0 +1,61 @@ +getHidyzm(); + if ($hidyzm !== false) { + // $m 是一个随机字串, 这里就不随机了. + $m = 'hDIbFprNaT0AGib'; + $hidsjyzm = strtoupper(md5($this->amsProxy->schoolcode . $this->getXNXQ() . $m)); + + $domStr = $this->amsProxy->POST( + 'znpk/Pri_StuSel_rpt.aspx', + array( + 'Sel_XNXQ' => $this->getXNXQ(), + 'rad' => 0, + 'px' => 0, + 'hidyzm' => $hidyzm, + 'hidsjyzm' => $hidsjyzm, + ), + array( + 'm' => $m, + ) + ); + preg_match('/src=\'([^\']*)\'/',$domStr,$match); + + if(isset($match[1])) + return $this->amsProxy->curl->request( + array( + 'method' => 'get', + 'url' => $this->amsProxy->baseUrl . 'znpk/'.$match[1], + // 'params' => array( + // 'type'=>'1', + // 'w'=>'1100', + // 'h'=>'520', + // 'xnxq'=>$this->getXNXQ() + // ), + 'headers' => array( + 'Referer' => $this->amsProxy->baseUrl . 'znpk/Pri_StuSel_rpt.aspx?m=' . $m, + ), + ) + )->body; + else + return file_get_contents(dirname(__FILE__).'/noneCourse.jpg'); + } else { + return 'false'; + } + } + + public function parse($dom,$raw) { + return $raw; + } + public function getHidyzm() { + $page = $this->htmlFinishing($this->amsProxy->GET('znpk/Pri_StuSel.aspx')); + preg_match('/input type=\"hidden\" name=\"hidyzm\" value=\"(.+)\"/isU',$page,$match); + return $match[1]; + } +} diff --git a/libs/AmsProxy/functions/getGPA.php b/libs/AmsProxy/functions/getGPA.php new file mode 100644 index 0000000..c167a3f --- /dev/null +++ b/libs/AmsProxy/functions/getGPA.php @@ -0,0 +1,55 @@ +amsProxy->POST( + 'xscj/Stu_MyScore_rpt.aspx', + array( + 'SJ'=>1, + 'btn_search'=>'%BC%EC%CB%F7', + 'SelXNXQ'=>'0', + 'zfx_flag'=>'0', + 'zxf'=>'0' + ) + ); + } + + public function parse($dom,$raw) { + $tables = $dom->getElementsByTagName('table'); + $score = array( + 'thead'=>array(), + 'tbody'=>array( + '入学以来' => array() + ) + ); + //主要是部分同学是没有成绩统计的,所以导致抓取错误 + foreach($tables as $table) { + if($table->getAttribute('bgcolor') == '#89bfa7') + foreach ($table->getElementsByTagName('tr') as $num => $tr) { + $tds = $tr->getElementsByTagName('td'); + if($num == 0){ + $score['thead'] = array( + trim($tds->item(0)->textContent), + trim($tds->item(1)->textContent), + trim($tds->item(2)->textContent), + trim($tds->item(3)->textContent), + trim($tds->item(4)->textContent), + trim($tds->item(5)->textContent), + trim($tds->item(6)->textContent), + ); + } + else + $score['tbody']['入学以来'][] = array( + trim($tds->item(0)->textContent), + trim($tds->item(1)->textContent), + trim($tds->item(2)->textContent), + trim($tds->item(3)->textContent), + trim($tds->item(4)->textContent), + trim($tds->item(5)->textContent), + trim($tds->item(6)->textContent), + ); + } + } + return $score; + } + +} diff --git a/libs/AmsProxy/functions/getRankExamForm.php b/libs/AmsProxy/functions/getRankExamForm.php index 84b4c73..e7ae9b5 100644 --- a/libs/AmsProxy/functions/getRankExamForm.php +++ b/libs/AmsProxy/functions/getRankExamForm.php @@ -10,15 +10,25 @@ public function getData() { public function parse($dom) { $exam = (object)array( 'thead' => array( + '操作', '等级', - '构成', + '状态', + '剩余名额', + '收费(元)', '考试年月', - '收费标准(元)', '报名时间区段', '限定名额', - '剩余名额', - '状态', - '操作', + '构成', + + // '等级', + // '构成', + // '考试年月', + // '收费标准(元)', + // '报名时间区段', + // '限定名额', + // '剩余名额', + // '状态', + // '操作', ), 'tbody' => array(), ); @@ -34,16 +44,27 @@ public function parse($dom) { $exam->tbody[$typeName][] = (object)array( 'data' => array( + $tds->item(9)->textContent, $tds->item(2)->textContent, - $tds->item(3)->textContent, - $tds->item(4)->textContent, + $tds->item(8)->textContent, + $tds->item(11)->textContent, $tds->item(5)->textContent, + $tds->item(4)->textContent, $tds->item(6)->textContent . ' - ' . $tds->item(7)->textContent, $tds->item(10)->textContent, - $tds->item(11)->textContent, - $tds->item(8)->textContent, - $tds->item(9)->textContent, + $tds->item(3)->textContent, + + // $tds->item(2)->textContent, + // $tds->item(3)->textContent, + // $tds->item(4)->textContent, + // $tds->item(5)->textContent, + // $tds->item(6)->textContent . ' - ' + // . $tds->item(7)->textContent, + // $tds->item(10)->textContent, + // $tds->item(11)->textContent, + // $tds->item(8)->textContent, + // $tds->item(9)->textContent, ), 'id' => $tds->item(9)->getAttribute('id'), ); diff --git a/libs/AmsProxy/functions/getScore.php b/libs/AmsProxy/functions/getScore.php index 1405bc8..9ae8435 100644 --- a/libs/AmsProxy/functions/getScore.php +++ b/libs/AmsProxy/functions/getScore.php @@ -5,125 +5,165 @@ * @param bool is effective */ class getScore extends __base__ { - // 这个获取方法在广西民大里已经无效 public function getData() { - return $this->amsProxy->POST( + //默认是获取上一年的吧 + $domStr = $this->amsProxy->POST( 'xscj/Stu_MyScore_rpt.aspx', array( - 'SJ' => (int)$this->args, - 'SelXNXQ' => 0, - 'txt_xm' => null, - 'zfx_flag' => 0, - 'zxf' => 0, + 'SJ'=>(int)$this->args, + 'sel_xn'=>$this->lastXN(), + 'sel_xq'=>$this->lastXQ(), + 'btn_search'=>'%BC%EC%CB%F7', + 'SelXNXQ'=>'2',//0入学以来1学年2学期 + 'zfx_flag'=>'0',//0主修 1辅修 + 'zxf'=>'0' ) - ); - } + );//还是要发一下请求的 - public function parse($dom) { - if ($this->args) - return $this->parseEffectiveScore($dom); + preg_match('/src=\'([^\']*)\'/',$domStr,$match); + if(isset($match[1])) + return $this->amsProxy->GETRaw( + 'xscj/'.$match[1], + array( + // 'x'=>'1', + // 'h'=>'2', + // 'w'=>'782', + // 'xnxq'=>$this->lastXN().$this->lastXQ(), + // 'xn'=>$this->lastXN(), + // 'xq'=>$this->lastXQ(), + // 'rpt'=>'0', + // 'rad'=>'2', + // 'zfx'=>'0', + ) + ); else - return $this->parseOriginalScore($dom); + return file_get_contents(dirname(__FILE__).'/noneScore.jpg'); + } - /** - * @param DOMDocument $dom - * @return array - */ - public function parseEffectiveScore($dom) { - $score = array( - 'thead' => array( - '课程/环节', - '学分', - '类别', - '课程类别', - '考核方式', - '修读性质', - '成绩', - '取得学分', - '绩点', - '学分绩点', - ), - 'tbody' => array(), - ); + public function parse($dom,$raw) { + return $raw; + } + // public function getData() { + // return $this->amsProxy->POST( + // 'xscj/Stu_MyScore_rpt.aspx', + // array( + // 'SJ'=>(int)$this->args, + // 'sel_xn'=>$this->getXN(), + // 'sel_xq'=>$this->getXQ(), + // 'btn_search'=>'%BC%EC%CB%F7', + // 'SelXNXQ'=>'2',//0入学以来1学年2学期 + // 'zfx_flag'=>'0', + // 'zxf'=>'0' + // ) + // ); + // } - $tables = $dom->getElementsByTagName('table'); - if ($tables->length) { - foreach ($tables->item(2)->getElementsByTagName('tr') as $tr) { - $tds = $tr->getElementsByTagName('td'); + // public function parse($dom) { + // if ($this->args) + // return $this->parseEffectiveScore($dom); + // else + // return $this->parseOriginalScore($dom); + // } - if ($term_name = trim($tds->item(0)->textContent)) - $termName = $term_name; + // /** + // * @param DOMDocument $dom + // * @return array + // */ + // public function parseEffectiveScore($dom) { + // $score = array( + // 'thead' => array( + // '课程/环节', + // '学分', + // '类别', + // '课程类别', + // '考核方式', + // '修读性质', + // '成绩', + // '取得学分', + // '绩点', + // '学分绩点', + // ), + // 'tbody' => array(), + // ); - $score['tbody'][$termName][] = array( - preg_replace('/\[.*?\]/', '', - $tds->item(1)->textContent), - $tds->item(2)->textContent, - $tds->item(3)->textContent, - $tds->item(4)->textContent, - $tds->item(5)->textContent, - $tds->item(6)->textContent, - $tds->item(7)->textContent, - $tds->item(8)->textContent, - $tds->item(9)->textContent, - $tds->item(10)->textContent, - ); - } - } + // $tables = $dom->getElementsByTagName('table'); + // if ($tables->length) { + // foreach ($tables->item(2)->getElementsByTagName('tr') as $tr) { + // $tds = $tr->getElementsByTagName('td'); - return $score; - } + // if ($term_name = trim($tds->item(0)->textContent)) + // $termName = $term_name; - /** - * @param DOMDocument $dom - * @return array - */ - public function parseOriginalScore($dom) { - $score = array( - 'thead' => array( - '课程/环节', - '学分', - '类别', - '课程类别', - '考核方式', - '修读性质', - '平时', - '中考', - '末考', - '技能', - '综合', - ), - ); + // $score['tbody'][$termName][] = array( + // preg_replace('/\[.*?\]/', '', + // $tds->item(1)->textContent), + // $tds->item(2)->textContent, + // $tds->item(3)->textContent, + // $tds->item(4)->textContent, + // $tds->item(5)->textContent, + // $tds->item(6)->textContent, + // $tds->item(7)->textContent, + // $tds->item(8)->textContent, + // $tds->item(9)->textContent, + // $tds->item(10)->textContent, + // ); + // } + // } - $tables = $dom->getElementsByTagName('table'); - for ($i = 1; $i < $tables->length; $i += 3) { - $termName = $tables - ->item($i) - ->getElementsByTagName('td') - ->item(0) - ->textContent; - $termName = substr($termName, 15); - $termScore = $tables->item($i + 2); + // return $score; + // } - foreach ($termScore->getElementsByTagName('tr') as $tr) { - $tds = $tr->getElementsByTagName('td'); - $score['tbody'][$termName][] = array( - preg_replace('/\[.*?\]/', '', - $tds->item(1)->textContent), - $tds->item(2)->textContent, - $tds->item(3)->textContent, - $tds->item(4)->textContent, - $tds->item(5)->textContent, - $tds->item(6)->textContent, - $tds->item(7)->textContent, - $tds->item(8)->textContent, - $tds->item(9)->textContent, - $tds->item(10)->textContent, - $tds->item(11)->textContent, - ); - } - } + // /** + // * @param DOMDocument $dom + // * @return array + // */ + // public function parseOriginalScore($dom) { + // $score = array( + // 'thead' => array( + // '课程/环节', + // '学分', + // '类别', + // '课程类别', + // '考核方式', + // '修读性质', + // '平时', + // '中考', + // '末考', + // '技能', + // '综合', + // ), + // ); - return $score; - } + // $tables = $dom->getElementsByTagName('table'); + // for ($i = 1; $i < $tables->length; $i += 3) { + // $termName = $tables + // ->item($i) + // ->getElementsByTagName('td') + // ->item(0) + // ->textContent; + // $termName = substr($termName, 15); + // $termScore = $tables->item($i + 2); + + // foreach ($termScore->getElementsByTagName('tr') as $tr) { + // $tds = $tr->getElementsByTagName('td'); + // $score['tbody'][$termName][] = array( + // preg_replace('/\[.*?\]/', '', + // $tds->item(1)->textContent), + // $tds->item(2)->textContent, + // $tds->item(3)->textContent, + // $tds->item(4)->textContent, + // $tds->item(5)->textContent, + // $tds->item(6)->textContent, + // $tds->item(7)->textContent, + // $tds->item(8)->textContent, + // $tds->item(9)->textContent, + // $tds->item(10)->textContent, + // $tds->item(11)->textContent, + // ); + // } + // } + + // return $score; + // } } diff --git a/libs/AmsProxy/functions/getScoreAffirm.php b/libs/AmsProxy/functions/getScoreAffirm.php index 0973532..8fac9fa 100644 --- a/libs/AmsProxy/functions/getScoreAffirm.php +++ b/libs/AmsProxy/functions/getScoreAffirm.php @@ -8,8 +8,9 @@ public function getData() { return $this->amsProxy->POST( 'xscj/c_ydcjrdjl_rpt.aspx', array( - 'sel_xnxq' => $this->args, - 'radCx' => 1, + 'sel_xnxq' => $this->args, + 'radCx' => 1, + 'btn_search' => '%BC%EC%CB%F7' ) ); } @@ -27,13 +28,13 @@ public function parse($dom) { $score[$term_name][] = array( preg_replace('/\[.*?\]/', '', trim($tds->item(0)->textContent)), + trim($tds->item(6)->textContent), + trim($tds->item(7)->textContent), trim($tds->item(1)->textContent), trim($tds->item(2)->textContent), trim($tds->item(3)->textContent), trim($tds->item(4)->textContent), trim($tds->item(5)->textContent), - trim($tds->item(6)->textContent), - trim($tds->item(7)->textContent), ); } } @@ -69,7 +70,7 @@ public function getData() { return $scores; } - /** + /* * createDom * @overwrite * @param mixed $arr data @@ -83,13 +84,13 @@ public function parse($arr) { return array( 'thead' => array( '课程/环节', + '原始成绩', + '有效成绩', '学分', '课程类别', '修读性质', '考核方式', '辅修标记', - '原始成绩', - '有效成绩', ), 'tbody' => $arr, ); diff --git a/libs/AmsProxy/functions/getScoreMinor.php b/libs/AmsProxy/functions/getScoreMinor.php new file mode 100644 index 0000000..3162064 --- /dev/null +++ b/libs/AmsProxy/functions/getScoreMinor.php @@ -0,0 +1,36 @@ +amsProxy->POST( + 'xscj/Stu_MyScore_rpt.aspx', + array( + 'SJ'=>(int)$this->args, + 'sel_xn'=>$this->lastXN(), + 'sel_xq'=>$this->lastXQ(), + 'btn_search'=>'%BC%EC%CB%F7', + 'SelXNXQ'=>'2',//0入学以来1学年2学期 + 'zfx_flag'=>'1',//0主修 1辅修 + 'zxf'=>'0' + ) + ); + + preg_match('/src=\'([^\']*)\'/',$domStr,$match); + if(isset($match[1])) + return $this->amsProxy->GETRaw( + 'xscj/'.$match[1], + array() + ); + else + return ''; + + } + + public function parse($dom,$raw) { + return $raw; + } +} diff --git a/libs/AmsProxy/functions/getValidScore.php b/libs/AmsProxy/functions/getValidScore.php new file mode 100644 index 0000000..147ea80 --- /dev/null +++ b/libs/AmsProxy/functions/getValidScore.php @@ -0,0 +1,60 @@ +amsProxy->POST( + 'xscj/Stu_MyScore_rpt.aspx', + array( + 'SJ'=>1, + 'sel_xn'=>$this->lastXN(), + 'sel_xq'=>$this->lastXQ(), + 'btn_search'=>'%BC%EC%CB%F7', + 'SelXNXQ'=>'2',//0入学以来1学年2学期 + 'zfx_flag'=>'0', + 'zxf'=>'0' + ) + ); + } + + public function parse($dom,$raw) { + $tables = $dom->getElementsByTagName('table'); + $score = array( + 'thead'=>array(), + 'tbody'=>array( + '成绩统计' => array() + ) + ); + //主要是部分同学是没有成绩统计的,所以导致抓取错误 + if ($tables->length && $tables->item(3)->getAttribute('bgcolor') == '#89bfa7') { + foreach ($tables->item(3)->getElementsByTagName('tr') as $num => $tr) { + $tds = $tr->getElementsByTagName('td'); + if($num == 0){ + $score['thead'] = array( + trim($tds->item(0)->textContent), + trim($tds->item(1)->textContent), + trim($tds->item(2)->textContent), + trim($tds->item(3)->textContent), + trim($tds->item(4)->textContent), + trim($tds->item(5)->textContent), + trim($tds->item(6)->textContent), + ); + } + else + $score['tbody']['成绩统计'][] = array( + trim($tds->item(0)->textContent), + trim($tds->item(1)->textContent), + trim($tds->item(2)->textContent), + trim($tds->item(3)->textContent), + trim($tds->item(4)->textContent), + trim($tds->item(5)->textContent), + trim($tds->item(6)->textContent), + ); + } + } + return $score; + } +} \ No newline at end of file diff --git a/libs/AmsProxy/functions/getValidScoreImg.php b/libs/AmsProxy/functions/getValidScoreImg.php new file mode 100644 index 0000000..5cb2b9f --- /dev/null +++ b/libs/AmsProxy/functions/getValidScoreImg.php @@ -0,0 +1,47 @@ +amsProxy->POST( + 'xscj/Stu_MyScore_rpt.aspx', + array( + 'SJ'=>(int)$this->args, + 'sel_xn'=>$this->lastXN(), + 'sel_xq'=>$this->lastXQ(), + 'btn_search'=>'%BC%EC%CB%F7', + 'SelXNXQ'=>'2',//0入学以来1学年2学期 + 'zfx_flag'=>'0', + 'zxf'=>'0' + ) + );//还是要发一下请求的 + //链接还是直接提取出来好了 + preg_match('/src=\'([^\']*)\'/',$domStr,$match); + // return $this->amsProxy->GETRaw( + // 'xscj/Stu_MyScore_Drawimg.aspx', + // array( + // 'x'=>'1', + // 'h'=>'2', + // 'w'=>'670', + // 'xnxq'=>$this->lastXN().$this->lastXQ(), + // 'xn'=>$this->lastXN(), + // 'xq'=>$this->lastXQ(), + // 'rpt'=>'1', + // 'rad'=>'2', + // 'zfx'=>'0', + // ) + // ); + if(isset($match[1])) + return $this->amsProxy->GETRaw('xscj/'.$match[1],array()); + else + return file_get_contents(dirname(__FILE__).'/noneScore.jpg'); + + } + + public function parse($dom,$raw) { + return $raw; + } +} \ No newline at end of file diff --git a/libs/AmsProxy/functions/noneCourse.jpg b/libs/AmsProxy/functions/noneCourse.jpg new file mode 100644 index 0000000000000000000000000000000000000000..965175f986ea84960cc54b3924e59c974ec45e24 GIT binary patch literal 18340 zcmeFYc{J4V|1Um5$d+tHOoddolBLj0C4?k|5L3xIG0D!DDP_qvMJQs*nlvVR*0C#+ z>>10Lk=-zZ#+zB(`P|<<_jk@c=X=iYckjRVJ@YyT^M0Gx^Ywncp0CI9eDD3)n*klP zFf}&?@$m3~?r~qBy$O&pXde&Hf8PJ&;N|E2|A6kC$IyzktAhnxK%dkf7iJK>>jS zq6ZELi*OGCAu(}L5wZXL{GWgFpUeMq756P7C?NQsGyeY_do3UdLC`!;CNIwk&^`$s zUJ0JP4iFdw;^F7^_CFo|9|zAqUOxW)+%6pu=AKY}klTG;-hJH8^7HX=&yM1L4&syG zKXm-umHm=7_XSP_NNGQN{ZUZqYI&=)?Ep>r{DUXaLI-4I4
+#v38NmCzsTC_2a;1Wfg4>dqI z#Pa!s`VRa0tLXzkxul_k6`2f+wk`+m5HHhz{`RMps_q(J2pvC){P2sD?{hoQr%A`L zCV^_^KkDrN&uYr8SLglFIv6pXK-0(fscj8TETI-S2U=&R#Am>(Q=z5i2)e*+V7&m? z?`lD6a}(!6rl|AR2mQW$2*KJm$jCaJ%f4_|oBfeW&RFVr{7I}uwFg~^Se*!@t&@`r z7+6`9K{K9Wk8v8SHUU)VL_=Hz=Z^a!*C}&%ilD|qPP)yF61mtrW4s{8MG_Ut)P|F! zpffqp!&{fs$oOYQhIB8Az*Bsq5ivAYD?fL7<62ejblV?Tzu&`$$r2-WeJMJLk*C^{ zyW5R;nY=8o0iJSJCwWqp5Kz|EAg0)!RX~m-l~!O*kO% z8qNNGg@Z(sUWawBNaxPfd~-98zT&)S$CXhF0~Pqcy8oD=T2(s`HO>T9(nx_~Erqln z#c|}ki6`p{Nv?3HWFuImqZS`lVHQ}hvP&JvP?1@xey0bSUr90IWdL7kp S86_;3NsuDIXLh+ggv_Thv;3XPFZI=tSzANM`w~*sy5jw<(vo zEDznvEm^uxh=&P6{V*xbCxDkT*?xwt93xup^ZfCse2RY|T}Hv`1DyLbaND+Xg;`|n zqeT(ht0&rXlExq1VH42z@kfzX>{1l3FIt2p>JdCciffh~+k(G+#8L5uiBh*-UmP+i zI5)XS{}Ep4(fHK(=*gqUrX2-^vE7z6wg0N9kwJrcuKsmZ^=YxGB?vY2%(*7~=$d1c z`c7~qriY_N%WWcy^Dk#5fn^~^H;ArW1F2QD4N4RnJuTvWN6lhdbzJWKy~@Y=X)XA# z=m+SOW;u2)bSBl=i+Y4o(&(dZfPac>44@dgU}fPb)l(}z3p#qjrKHJ5mqh8?hdw>9 zi#+PD7(ka~@B;&7Na)xjT(ctLTjS8$v6pCaRkQM>e@OBhaZT4t4^Y>49^OkHi09*4 zA{?P?T4V>hlKTkI#0=pX3s#JN7*^bd5+4e}IrLH`?nY(Is|A@WZJzK rn19{-Oq_k|=q${yM z%Al@ja?W<@S98_r$yx9xgg>8rHqvvOnd0j}&lbiy2sc=^y*24%~!t z_-_8us+g#y$J_PR&3g9OL#X$q$hwOzH3wR`HG91bQ=jMgFT5C9ar5Q6X g>U$(+%!0f!Cy|C<0*8G!Bp literal 0 HcmV?d00001 diff --git a/libs/AmsProxy/functions/noneCourse_.jpg b/libs/AmsProxy/functions/noneCourse_.jpg new file mode 100644 index 0000000000000000000000000000000000000000..70e7462ccbacc8f3a29dd9a4f45a699e652370d3 GIT binary patch literal 100959 zcmb4qdpwixA2&jx wj6Qqs~= zQcl1j_2<3RG5a&&AyQH ch_DJcah8EG}Cb- B;y4T?&@fafYw((8b}b+YoZ>*Zw? e6=A>+U;h<|fq8E&ZBE8oBb>!7^2mg9rTrCU#ZFtOhg ze4iL!Mtz<#Cv-^o=c6Mjgug*iOWPCz-D`t%LSsCRd6GlJ!YQZEBqm)=O-s+n%D+V` zpx BsWVH7Wt_ z{)b55_b;7mM99khKPpwFWMlw3*U7AtlaZ5=l}(ifc(hJMO<#70#bI^1-3FF8jYINQ zhW>V-XgvIqn^AVjks8hQ0SNbh1;)ppq29-Q+j2S3`V`onkYmCa1emw=FCBXTLL3|c zQi!BAVuFH0*64|ii%(di>7OgfDgU7>H;?)s(n`zzOI+=J{(tFfdHz2Nh5sY*!^i&; zIro359FaOACI7c6%F8P%D=I1~t0@CbZHwAk+p=xT-?r_)&ERh{S!+B0Z~FthM0)-D z^-79L>WYf$=G(QmoBw~eKN6{p>;AG&6%ekZ)Y5melmJ9IMpHGXKn}C*h(foOfsN`v zj6)3hD>liRC2rYjYFwc} -U<=%$Fa+Bw3T}fbLlU*kzn4T> zfbGV3Nc_efJapM%i*%XYIaH{Wa}oAZpe#RLnqjwP6YLU-1vwK7a>y~n;_*Cmcg6_X zu;bDOj0+|~4x^n$PE|3wf#P(R9R{aTIXY@7a`bJg8ikM1MHNQ0u0eWwciBXC 3W5xOY>v-*NbkyJz%)`&}&(xW)EqDuUA?P95IsH%YaYE=Iy$SV|GIxeMT5tNlsDy9#jj85%bvcS zOrI4$YdZ~nAAef?IqGa?D_D2>Uw6HCh1)#tc1WkZ?O#_i+96lb ^?vV_^Ems^%xCspobAjr=p!ERlH8}QXMeoQiaLDfK*o3JQ%`cV?;q$U%XGqt zV=y}~EQQ_3`7+;ObgSo>BqbdVA+sR|?gq4h(eQ1aCC?UQlr*-2(>~=M!HcE3z^T_% zG_(Wup?4quA@zZkDxaZgzWZC8z5FF55IoI#cMV>~a>2lZ4KuiY-9`0-iy}ICpHo@z zl!I?sa2t37XLqHYf2>N }Ui<6k)=NQ)T_LhRd zAgl{GK?6pi6?p}Tu4g-8gt}CO;vfnF<*}gfUQ`b$#XcOv(T+#;5GKT0 @G#ioNx&x1c91lr%>=)G}0xt z*$4|&Or8tYwX%{<6W}bkag+i~MNqG+5NAu0z+8JYY$>^iNu$N}`-G>jS3(=%gK_jL zY5FFjbB{zeKi|u3+2wsdsWWwC s_EAj+G)4)eH8ID Zr(9 5xNHc(1piV3luvHd%317g3?T+(z9LB%k ouQ@PCe#6+;2i&6 z)h|vm+wbcm14;$^<^{mIlvUhjNBY!R<;Z^My`k_;JcM{t938B9?qiTBj2OhzNGA-; zeJH!)6P8{E!J(-PK1yWAU?gy8BBnl3+ugmCfNDcw33hc3nRq@l4`p5ph8l#Fx>izI zxw|oG1#AJLvcd-;B8$BGI&-#CZ+Aa5tI;_W?iOzEG{z*gMl!KUN9jo 0VY#)B _i4nq!EIiS4 zfd$S2!H748W~7nICdEqK%rGAZp&h{`(t>P)Cu*06@ybbgd2jaL4wbvR&Ktkg#Xh*= znDj#6LxZ~O&m#@euN(dJqbK?9cjwP980QWVX3)p(qBPD-jcEVw- @oE`Lt t_v{Ls9=OLl`XdVmZkRb^ujda(hkf>{l;Sz}~K|-R{ z(dqWPjEVJEwa{05+Tb!LbMt)?%%F6K6BD15Z U^MK&{)E7-zGC<7wrt&NT@PD>SRc^0o>Y zhcfT#mJ?jXdN)7orQRgL0%I3Ax5szy4S{^n$oTMO8rJx0uE%*iCDL6T1U`XR;6Hi` z?Mnar@>CsRXR6S;=6EW3@;oR1^p1P2%4D-sjkuuOL7lBBfkU2%;7D0L9V|!4*4r@q zL+t!-=^n%SPg0cY*7_}xu`!s%zWhvwy0Ea-{F4Q~jw#fkS8^2}CaC1L+TFolwqC|p zB0MFH!M3&}oliy9M6bLljwWsV^=%3!n|pqH@8d1XB|Q$huCMk7J0D)}I>`3``5k{= z-A^7Y@3myJcf7GoiSnAEdDkZ$!R^(yip;%H x&gEzzb8idYLp0u>?#b;ph@yPi()ZvNfVcySwARw9B5zR z1M44mKg3s^&=k*-WgB+#Za2#7?A^VIVWV86l39!E+u|RTuS^f-yskNedPw By`#96l#JMi$ z>-Cp4<_+~^KNzVwY$C(OHkV}(Z(;`0OaEM)a+9QU_4R6$R#Wi$t!c8MCu5^e?1cSn z`WRMZB?-9tDS 1qSl;wa6qVv*{oG?S_h$Xk@qFlbxB<_@ZTeM{tM ==-&mWs5e+=)V|LTZ@|3}6v}tl|I=6@wArn6qgrdfe^oU9J>SOu#_|z63+S|b zG}c#D+t`=%aVpiRW}-Eosd*w%M`+OSWp`lY?T1#UM?U5VUa*zpENjm2#c FL83IsSL#ovin&r@78 z9+6xPDxq~ssL0#REkfq1bFBgQlgomJQi|%r(>Xh8v`yAQ4?|RVo;vt@3$QRoC&)Q@ ziX1nX%(+W50v^J|4J_JYCpa|X=D{Z6;O;5yEnDMDAOo?xxw5V|A-=yKRri^vpBs40 zO%P}CoC?I+?qo1Df!@`{c|}NZ;MD_9+A%00;8N_Me>C6%wHc74Ex2+*INcQ=ftq@u z$Iu7DfwnFFgSmC6NDPMR#ulq;mn1 gu6= zH3htn8J~IDuh2znp3u%ih9l!0gy jF&hc~p^c0ATm97>+8kp6ZqpL|~H3jCGBj%%Ijx6Bm6q?kg*F5xhWnn9#c;$i*a# zH|ZNb`7mBOdTabfu-twD+_d24cHiI4)qOk5ZWcyza7ca_&z6)4s&{eC#A#Ek#p>#A zWm5&|OiTbXni~gY;JMeSBmy+AK&*tt3oOt=4W4#+B)))-g+dL8XpF!KOqT@YA}I-U z3=vdMM1_}pP%JUF2W!%gvJ$Jy-iu6W&pDgkSeH|@8AXOw`>!nSzmP~&JjXC0go)Tf zuP_cKmkcLhT})irnIOv)0>sL_oFt(nWZ-iV>UZ4b$TxPr|HkD;Y8_IwAcJ9ctZZv5 zO_e#ylM|`fTu8Dx$f;Xw87inS6uBFDYI1|0JL#hV3tR%bNMzpM<|*G5kGG}MH DYKm39+O00$`({Ipr_HT%g8qjsSQ+ip5CasdEhh?r}0fP&;n0 zm3uwUN+ajSpi$Uv5}vpL=jXnD#!JY`cQIA9a=s_F*umP7!Xzr|u&O8vg_Qa<=u=om z#q<^V91t!j`zX$PaVH`rP6OrDM*Ij0>q<8FaJtV*Yx;VouV3#js{9T|YIj&G8p3f$ zbXlHxQQZe;9xb$E@L_-(P(_x&faRVzRy9@cd%vtj=m{08vr1J#ikON>jrWo-AC`{L z2oaAD)lf3dl#+)vCog^IZmVcKo>?Mq&m$aYU@{0l56T^ik%WJQ?LaNOIE#A7nkebW zSk-75e7pd!IDeW*Jh?^7Iiou+VDA-=B9M#m>ZVBVd3B8_)O_=y4o;)D;T^W2slluz zEQm7Z`8aU+vv&LAk ;qOP;nRt^kgIlM&O=M_=wRR971a%orb?!N%wBE?eHX7H zZVo05ZLHj(d33Az=D|TCai^`EW6APo#z&EA(ENhGQ`ecxJEVhN=y~3*KYt+h_k;AB zbJLY 0o$7)XkCpr5u+=&OX7RfK@3?#m}D?pRh`p-nE+rxH)* zL%zxl%n@e31ophB{NUF;zEb>!Qo~@_W1ka$em6f|ct1`1U{!_C QoGN86lsz~mBLy_%~?PRQGoYvifKzB}{^<)iFz%Fx`EGOm0ODoJJz zmWr>k@71Xo`wBTe7Sc!(CDfe2tRO4AsCKgrPpa+|+mfek;xBU@Pt8?i?+nZh_95w> z))zg`J}? lt@X54+@ &8fY;+J#1M~lXo=g-G`kDWzMsrS7cc6{CxiYp-o`{Q1^uW!l< z7tic*^k#mx)IQUPi0F1)7?R1auPz|k`^LQ<;(8%3+aIatl_A59?VHe{HyA_2L3)jl z-El~dU!0GFw^C@QEn3>*Pd?=NR8--TgZUGlh^R jXH`yZ*) zQ$tD 48g}M^~G~PYpKFHk~lQBec{K##?Yw#p)6#`k+BmBPsd8Ot?V&t zY??DuJSPOa6ai0!Fi|cjCXu>_{$v?;ibi9qxML*HK+1> a`3ulJ@dsT_;v*7wz=6kliBx )?iC&84&keOuDGZ%IWJ5^A+V1mV2r< zpc It{@q;9e4os75u4jIhHP=aA)({z#@Hz1%CaQg^SdIl|>2V@pvD=N;4tHvMtzIp%m zjmXQWYUR69E!UVO@ta;-Z!v%M!nJ?z7l(82m0ZGs&jLQ#RZ |z0hr6_#~6yOoQC=BE{>!zTMKe{*W!9 z=%dRjz|>rXs)c)PIIaxGzl~~hl~7gT{3@u4i{X=ZkA5Ljk-MjqPVfA%8csA)KD60X zEHv*&v|nHDCeTOh!-Z&?SW$?Uz)-#67_M~&tq6!Ss9;zm$CgrH_vOSV MINA4tM|-1Vr4Lo-W~I@wKdMB^Ns( zCkcUJKy63YKY7kIgel*xJ2SY8$hv>ptb!V}aMQ2Q$7ViV0K^*jkWwrVR-&-@oQAS+ zv1*;G5MR@48sXxQ39u)xS7i=9l@M&z-*9c*95K(*{AWJiA$~$VCjCdk;Hy?B6wWHQ ztI)>*i(tvfhUx-oZ6KjttV1E^!pnBXGr+eXbW$4o>qEU2Wi}a|>YgyG( HWNfv}k0215 Kq?uVawSI?)d1mi2@a=d55;q_uDpp0@e?oOH>h1l=8K;nYuW&? z57fQ;-1EPoPO+c@3%*r~&$U9Q14~+Bv}RZRlde|M3tq5Y#U ?=>oHjIWD!mA&&b0)z)QM^jM9{~^(`a-olfcd!yviTS1lhVcNch16t6Tb3)s )SGodD+^xm5Um3!&uoy~g85_FI+9hKq9{97#kZsFZ>a2C%UbF9OU3 zh<)>BFll02dshiR5 wihQU>$-FTli1X!Xdz#MG6QwpyYT#e->ITqg${H WK%&@bsRwK8j4YhFQo{xox6xoLwgcvR-GX(%(SIH2~LP*Q?ouLYyla1AuE!? zGVr`}kLv;0i52fq09ddhRw{H&*9N(EM0j2}j|FiO;uJGRTmX0|Y0I4?d0o3>w^F@j zXE^OI@di7JNl%`o`q6`W4#WaTD!h<~9;6dcqDUYwvb7KE;^~k^09O{og@(GgT#+*$ zBKFg&o!@y%CutpwV@mR_#FooP#mIg!2F)l1Dq_Ek2Rm@mfYo;*gHW!bvM^2_1&kW3 z4as3=B+mdEnAeMq^s<{&w{rTfyuSH4r$)XBIac$`-ffr+y7cKKurlL02|^oeTcoOU zCdh)7Ye~n4Kx0Cv*&rl1x1Ps{07?ZG7;;En3ZqDY;aXAOr#&`VrAykD{7FHWK5JX} zSU%oEe6(jIvidf_1zLu;Ls>AGS{v?06@|M5hcQ*496LrXAoz8WRGd191;W`9P8V*D zy-9F-(LXG+o3Y1C_c`k6KIVC9R46?h`{XQu$WqcJ^+k9pqcj+A3FsOnt)Q$A&|h~5 z9iPDbG(|XU@abggofDqM-0wz4XQHcV_e`HfReUgwlmD!Ntv4;mkc0q}=MRP$P$5JI z0R}@P2a@n1xm1lJMIhG%^1m5!LRrFV51(83zICzjovsS?7h0ZHqPib|yFLPz)XVv^ zIv|Zeq692sc!p4s-EHrX&ZYt}2VsKfASrd_se|&0JZ>a*y%?APr@tI}Q!3j7M1Kvi zPQjyja(+#BycM?8&jLN@5ecdXJRS;5qKS8xi6+IR_7FF^pbnG3v*6$?+{(DD090`` z^~?RK+y}9}!_vD0_8i~W2$F69M` F z$;DY|qzm118YS*tk>mi1t*>E22j@}NojX-J52MtyU{tMRd$x&R`1Zpajpu=S5MUZg zNh73zMpQS&GS?j zNOBAyM %0El=nrQ4Mw z;08idCiZQ<8z?ff=p8P2eB336^v}J^iYND%wx2H!Pv|cOEM6-hn*s}WH9AdF3PD&{ z;8WVb1OSlaL5L=6e|w<@XP_r?dB%x0KS8GE7q&3&x%%GL95z!XWSrXnD;XPDOcUEu z1`BvL8jsb{m|V0Z!a>Z0vhhUxniY3vghPcmz@S_n*uVY?5C*C#6km9Fd^vrWVoFN> ztn?lOvG71Yq8047zXZ-(D-JN?gDME9DZyG bLvaiQ@;=mo~N+RfX)1H+!fE7d-gJ!gDk0jNQ1I7HESlP8de6`kJJMl%R>O5 QL9U&Hp{w_?_v%obcZmV=madGT|{M>7Ii3%eiTuS&%Md^33%F1&62r{ za?A=^z7 br;50gbON)B^wHm~XIErwzR z`SMK_9VhW;apaZ8;m8}i* 3YbBTDUKoI0i;)2=_z(>c*79Hi z7Rs>ZeEqdDaBoVZJa*y5mQ3ugAg6yy^cv(fH`?y|;CibM&SF^uf{B{4t1q)-l&<0D zK;Z!MA*+(^+g*0It89$2U%c`2tE55B-1n4|Z&D9QNGhfEMdzM#KK49T#C<22T{cK4 z1S(#E;JhL(d@8dJ0O6q_*%m `_W<=K57!*2Dt*I_~d8x{t{rDc 53%69 z^BR*FhI9bY%#LADOOSJVD>#&tE>`d+gu4K_)hBLkFrpri+swLPW1@`}28bOnT#XbF z3y1#hXY>6WG6&JF8<|DAS34q;MT-Z#?Th<;B*KB{JbJp&NyxPpm0=+6tXiT*dO;a0 z9@E-LP5{b@0q&k?AJ@*x6h^KMqLfmklo1@R(G#$R0ZFuQP7_1&L^E8#{?h>4#j>Oj zfr0~@02DVcU36LzV6y_j*%QB`Cbz~bgSM@P2Q3ub;qE}&3A}UHX97zxbH~ONfEnHS z_)r%>$kRw{plo7=PI1w92kMw)V}z=@r;`uN02;^23fgKj@}leuH_5^5TDrbEqtPs4 zd$EGnUY=@3PYL0XPQ3my7B=lY2uq{RHj%Sar|z%=bQVOcs}Ff@grKst6^Zlu72d zQ2fcM6ThQ@_-hl| c)y7(6R}75o@jT1xW3- zR{tTDZSZBK7e>Jw8Z=KzfNB%jY1!ClV<46=;R6oDGY}X}IxQ39AhMF;H>Kc-itIdY z2@=?XV4KZDX80fIe?lGE)88Z9spc#4!ka{77j3%YEU{e}zKxc9kZS|gKmSK+i!jKy z&3Fj=HgnRZXb}E9xi7<%Kez_&Rk8t32ADf9)KC$Sjf_z49GS01J?E(K`iHD og7wgl)y=)?shrg{r7@dlhFFeJ{KS0i+goj0hlDz_4Fw zqKBU52lqGf-jg#u6-tHu4eUl<|3g&+VSn_A&R0J*Oi2^ptnvOVklVwI+A5l6dV89L z5d)OCBkM4^2rG2}22G&=hO8jNHPcIQ?u%ge)X2#T_3!p>{OLx#gmh`QN&+It1DNdy z6UvA^76`4T2w@xn#}f%;YJ31EhvLa sT|jqm5?Pw7KD_I8P(+7(zAER)Crk>f;R zVm^f?MCWl!2b$&w{++^y#x6Y2x_a1&3bDI-dYkk5O60FOhpT;Y03X*5NxZ|csTf9S zBv2g$ko!yr?OZ2=kP;k1fef*=w>gUoy%X(oJ#mTc;`I8f*!L1MXG+Tb?q?Es>~N9u zy!8WyoAp9KTT+L2eCNz#=h*U+o}nZ;=Tk8`hni(MipdkiNLFnL(V`9og;+tD#?e4B zU^39O0`N-h{l3*x>h<~pb*P n$ibzBr4FGx|PJotsT7h%`teP2#;J596 zG_HX7@}gf-%~~pYa!h#nji33b9f4X806?xZPA1nHfYmVqgpCz$;=<_(TD+aYjSEfU z=K*>U7~WVv@>J#<_{{wJ<3b%~VtZaQKBEFsOGq)r{`11g-c|k;d`#MSkCH$I&Rl0X znQjf_+gw5>#?{5Oiw&%@6~0IVDE(R>fndfONFal%U{G*gI^7!+ZZ2W#W&V-UqC7tB z9b2E-SCDSgB~Q-W>*Zh>*A~g*W5US@6G78kpem9Fi;YhSxg>y2ruU{(PX`gg#8kYRXzDsr8qCzQb#eBWL$62ma;PUDA$;6*YO`myMl7C0xKm z;qhg776>qn!aCO?92ErQwSbotQ|quT6_FJ{T^tjyZa1kzp{^Bb0b{#Xsdm@FGqp `QhS!q$WLk(^t~@EE{StU3XFu+3k`)0@znYB1n-|Ss>>3h7|!>hpTuun=OgJ zx&Tm=G2nX#;lTa|P7yc6-4ka}bXUMyL(2r7PDIDD#J7z1BAVOs&%yOlRxeX_ZWugi z-Pr!%exIfPuHr$8D$l&Gqxk+K6Gua0V~+OoUPLVH)BIBGx~7T`KQ%#{w>|(9BF{Bo zr@CD$HXoV4Xs_G!*-$)JzKOLnt{o^W=##H<#Eby`Bu|}V zX^Mw1^l=l^z(d%|*pXrE>104m&dUa?DPD1pxscqUJiC2gWY=hBU1VLPsoYcF5?eY% zNtkLU*i;I{tF{z@DHH1wsfsVi7@?5T*+mE>m<5JFaHf`r0fZ&1Aj5l-P2(ftlGZ)& zvl_h(8plmOui8A2_kPGA7G2g@@o5@r7@hDU)J);571XP>{KPV*Z}fI`KkHG|#L_rK z{-|RwG^ & z*?PC{&=GTiS>!!cU{emoAYT94;=UsGVO-lt!Tz8l3!5lzmrYLaLO_$t#D&?B)2B8? zIM6E79(+c0r)AZP_Y|%|%O7%GWNCXG71jqI^D#WOuz~fk+NHs1q-P-km|(r6R&cf2 zpI)=DMb==!T7A*%1v2oWjxm~zN2sYI>gkzvVG^n--5?jCy#{nxr~~CYLoeckfRw2G z^j=gu&jJWs>ID+GTHCy`>npqLHVG@LK; (aDd`ysh`Fqn~w`+{P-3aw< zT@BA|PMq`Yb$T$R8nc>G+%!>v#EK%eyN0W(_+8Uk9CfTp%e!K`mZAbjUOK><`i!nT zkpsN|HJF#qM75ou0x_4GJFqna?8fa9xU0kcoX3B@xi3^(6zu+wp&p?CLHF_1J0=nF zOmCmE>I Hju#Rx9;ay|+ KB3`=^%Sb+>-~k%}@HGG3U=wt((&>H5CSt14Xx?mhYPMR{Nk_3D1D-NjX> zed3Az1z)h(*ac%*txXR{M+(1u8iO=m@PW{ZBl%bokfA^&oZL4%i#MNk@$cw*YFY#@ zWOD>?J`@T>mMtD$7)mGw<3!hf;A>y>DRLgzVR9m@2yl*(EL#UoW{Fze)f3&L #_k9yD_ezm?^EtXo9sXwc}ZQ4i~?4x#H zXTMbV3)YCdy_tB|fe*m0yr$YS1AUAbs=~~d(!BoCmUCNVEyiuZEAKm?gVmz>drI0t zsfILl<-^{FS_%C2&ZUU4UHh8tzZ(XN$_@ql=`Ez5-sIxJf!(Zb|2Vi8dkvOwAld$Q z=Cv9ANTe5V;My0H^oYb6L~SDK6^Ts)b_Qh>0(;gd!eDXs)1{-4g@#zlqrhuACmO-< zt83CIU9MXHbOtb1;GEgqJN{;{@yR2nH>Jg^D`MWfpiC@|-rU#|unoe!Ti=(ie4&}A zy!8fv2|Oi;0Ft?bN$R*Sly>>(5n$p9=`9cDXk>ct5amy#d$kqhdnq z3_n4lgBltE0E7{#;lA^S3-r+DI#93^_r$|X5$$^H!T!3c5tP(9lV15koyfe&^uYR- z|7pqy #ExYgTXtB?q6-642(K*ISySf(GG5Nj*l(dUTpE$&!*73xhh8T z<5!W3ccpicY<|raQ@cr(_(QUJIGt7iTXO}}705K|P!k*p;0XW=&EHClYm~yl#oI2H zzH2J?+$u@fRNp>wsQ%>$0E`3z+AZd PqE9?{s0$HfVO14ohM#~G#-uSH_m}48%kB3 zwGyGz?#C6(HguJ>glNIU;B5*y5C#ieTN?pEvfMfDs&cJiGr5@TDT6C;`^&&CKj%&n zTA5)NgibMie)({!oKv=3My9HBcH1r!0!J;J=Eib_R~C^$@RV?-ox3NDu5~{tekX{e zB91#}!&H!@8WJ(Ns$Q}7QiC)s)G*859VAuBB|DUL1z2lBc`ja1CNUJ$SjoDt*dD>E zWHb|Vrb2jig!Vzof+x2^Q9wlU7%cw??g#7p?%W}09ohb5N>0SL%J`ENx<1^Nh!2&F z8bnw|PlT=?W0iPc2~zp=l^PccK-N42$zTW;QW>960Uw^axKW)HUY(JEnK0;v5jHWn zsveVNKHhEQwqOLO{Nsu7ypT_&`iMGU!?gmitzBA9ruD$x<>cLWeXB|akb>cwGt3V^ zuT-#;kjj$A)t=(R-yiGh+Pc@B^?2-?GO*7_Ni1r*!u7p*wE5^GM_0*3tBT<#H%f*d zZ%*3hb6`x@HfEyIX{P-3`g-XPdgj-eV*krZth|FUH$5CH#Ny%EFOoY6RgWhoCcY z-V!au$H%YGk*RJ|Q@TDrXNlse$ +;v7Hpa}v(@fu8+Q|K9aRX0SAjk68 z6@sgA7knnR(}Z=l0>NO_jq9ny 7@@^wnIX9~k)IoHfn# zorf)@Z-3mqI_2>de=v!<^16R?{K5iksbTwLr@x)eXQ?Zq>QUweU?j({2^dK_8N6%M zc=PDkg=Juz-{YSDi~}C-sU8hpd-(6T4~}2e4krG6_`jWxF{|UiXPOhU|MSMbBZ1CY zkFT)@&laq8vi^SC517z@I@c!j7X052{q2ldo6zfO;Ok4UrLH4u6Zkv(oVET>)o+bM zbWV5GpS$MKS+9JIhrjf)8P-24tOH~TClCmPkN ?#p!KT3df; zLRWWP>D{ z*#;Z?$$F68hlZ(E7ZN6RpraZ~&_p<5a?{bgmcE8ZZwcf(= z`RA((MF+-_=Lh?vc8o1LM)j1RU-|Y&%E0Ji)19TF97VCk@K?Q$$;BQ1t&hIG{Ug<^ zy;wb8iZ9F4>s%e{s89Y>rwDzUjyQN`ao_q47ZYsd&%C|xN9s39d6VB!bvr9%cbs(D zHH6zleO!5vA(&ySc^1aM^JpXgU-PA<_rm38zgG=>l?n_^Z(Saq@c>&YXHa}l3bO1^ z?9y?qp!E%u>8imC(};rxUz;!3Zg2Mc4Er^9@T~%3lZu*67IS6r&VFdf-m&ve(H(SV zmU~0!gMyd~GsUB)-!`v&T>g3S$vs2zHrzi(RJ`810TI@ctk&tal6vpM8T3j`OP%}t zlhq%8q|PCJpS&}*1G;RvkFa&11Z>~e)c-~{)l|-+OWQ7=baspb-ykklyD+VnxAb^* zetWe9dG#+uJiNUrLaZKGFeC QmbRqbnh pp93iPgq?pS$pxzFPCL0pPaYaC7teucv;8{gHa| zZssFLvrFlnfLjX A;gN1}wcV&j6K9q@RA0FseRHFu?(5e-QsQ;1 z^ZJNWn+&I7&hN|tc3NGcB;i12j >PLcWZb*UYB}ZLfk8kZ+D0$@xX6A!-0(-rgShOzTn*=-FMO}1cGle- z7d@YkISYyx+)7+|zr^{qaIs+fRO3aiX4s&g-r(=)P3r@`9z1ujp!JUwCw}Ee RcmuTwOwNZ MR{zm?u!b7{?lw{#tuglXBre=8o zLQI#)G`}n_|AvJSqNdh%s@Ek{fBXF&FQbZk?`~4;V!{Kjj}FIl%NYctwoQGwOUQv3 z<2gS3xC^)pqc6MY)XT(<6=8Mk8{Yx#O`6_Mo>F%H{cuvs2S2I36`T*E%f*w6fntXn zyTZ|@gnUAGROD~e^*3tSGg{t(M@%UK{Ee$ODabL{(R* u|aj*XJZX&nB(k|_cP;9_H9KroWE%>DEfNv{8CO? zQ)vVTEIN{V# !3nzrD_6Yp$akp)iN3s8EsjWJIq; z4%2eTvA%BL-?(sr`=aC4XNtEZ2U^ZIkT-;*yH7sN%QoFPMPvkCxOl2=Mb#2e?o7o? zCM$1)M6yyIT Z(=hrP};MFuM(}Gt{OupLC14ix(Jk$O=&7yk~!TrWQYzMD2Ij$>4 zDlu)7Lz&c%y*X08-054|-drw?XYipq;xYVCD~YRXj2@ypDD68Y5*nId b2CoiBS+&nE{gH}?%NiR~OU&?~)7U(JoQ)Iy&iX#T z(a*ac61P${aGi_tnfq!r?&U3Eq$7?wO;ZDwOLBcDnfMGF%_*Vrc8krl{9xyguQpUj zn<|omEIMe~V!wyEj=e4$Q|$Me4eq%frLoT-))>C>RJ&H#a`a8&>88~`QY)W0+j~Lm z)!qX$VcqFp{hG87uU{T~vD4<_>DStin%{0-`gCByRy_Q0CH3p}# loff*m43(M1IVM{*00IB}H z+Vp#|xz}Tvny{a`(%b+To?pYaR;H^*x1Du=khQ`;o^UYkTWIa-mABnrmzuwh7p1EI zE}h@!Ib%}$>kjqp*Nbn(wrg&A*8MB2_L1}S`4`QjH CQ$M&~yqw0ZWcSgLrV%+?=Kq;R(6TvklgM=1q!u0fPs zN3(?CGP-jCr8h^iS$sFR^3h;qz8|n$sq@d2b}-T58J1(ochAq|=rt$k Pun}rj{6%YziIQuy>^k0)fEsx!-f>)%V~q zxb=rDwyegAEW1h#Ob~1(u5(14Qsfb;xM2^EDSojSy`Lj-vaiUvthI?$Q+Qf8`xbPl zsrTs=148+yW?z7ftqEY*Oq!lN7yJ$d >vv{8A59u|Th-qrl!kCYR$=RWL#bi$H$!gZKz*c?7D z4U@Y=Az!QJIsvTjxod!4Q{l%?9+yeZ$k`#&mGDl1n4xj!4Lc%q`lO=9m62OcGjp4E z7{?lIP~A#@WuqT!XMhuPQMbdE!|}80%}$v?ZXWx*IC{{LlH2n{OkpPkkv@R9zIaIv z-hF1*P5)=1CHdvcC!3SDIV<1|yWSj6-57V(($J^7l*WPI7+%6}E1TJtSWDTNR$0+2 zad>bB?H!TzJTg*z9-;n98iIm-;*Q%x393EKhm=BSBQp98=d=yglgT{CiQ{@db5Ip- zOUJaX%IA@dJt{DH9dc*Ud#PeOAqaea%L%$&BZ_ItkaghPVyN$HdbMM5eDyW#>Buvc z*Z`w+m`}si&yd`mp-l4~n*3*qdKU7`_Vq{Zj6`%Oh0VJiQvQNAQ_~dPK7NQVzi^5- z%<+ry-S|ZR_3tJAp{oixXqL=Q{oO5 !DnWMXM`EMHoK h zm}hajGPxjSkzb^o6g%#MI`sMBg_+6jy46-mds_ZI8u&=x)U~UjDr2>#;^-bnfxJrj zizD=PYF&&m-IH=eN!X*5Aus>yc$|`-Rj%x|n)B9>gkO%{t{ZNtW|f(5Og4Sw9Z^ig zR-D1Ja4!fI-UH(-^o3TBbsn3ZrC)m(9uLjC-}2&mn$jIv2wUTh)$`6~oBjWYj(wQD znDpT~gkjwI(E-nrXn;zyCY>XU3TLIg-(=M};7-e1zTS`>${2G!9a51qE$bK%ckD~U z&4Mk7up_Qm`1tI4X1Te2!8ZN^7-4h(1=~<}Nbk$K98(MKk@f=~kG =HAEuh0 zd@sp!xvMXItk*Kyz3Z^(VP|Jhc`Wlm+^WXOT})JVOjo*oUK-VVTkJ}s>!I|}6sgXC zii6cddr{+=CLm1Kp%3?mH tuL+=lEUv5n{4KAe7`FGgL^3&eR-`yPclw z1m@fqy#2jwvX`e>Ijfrd;{CXK#!YnYtI$-9ONV0t_13fQ{OQRc=O=?@o#TwX!^wV+ zUT-nF*!HM(L&i|kWGVK(Q=X$nfqKyA$%i) (-%2W8Q4M-En7P>xPh@$d$22OAoag zGvM7%0$yV(@E8ynbBejIEanJ(QZ?m;Q4u3I|M-njkBeI^?u7+9(T<#CLeZ* Zt)(3g3Gxxop{fQ0UC@2oJi48V=V{smd{T%a z8Xe|oS8{dK@eF@XV$k(s$4YkBHSZ|5Io!%WM5fH{I#BUzZIUrI#{A`qNX}CAPMiaw zds!df`Q+cehZ+@40)zZIqpY@`u8`Sa<$)5X*q&h6{=>z_6-!4lRv@o`|G2o{{pf;< zkw!Oloz$+JdP8bj*{-c0BW~?#N>|)2= Tc~1V(otqwg>RiTKob(f*KIK){{wPnq4g70+5!_Gd&gjhrtv^z3GDp z=;nn(zt3FUU;eYY_uT*C>N^0MTAGD}4J)xwgbRrZ2q+R!u+V~{fS`mbMIq9z0yd|9iu(j;S)Ma3zjXpk*M3cX^% zV6oRZ-(D2wM3o$<*6=bkE8{ML1$km0^1Xg;%csUoF<399Xs_I#uZ~e;HYGK;a}Dx3 z>eDO{1+`o6P=3q+m%$1 #0mIBeD{ho;qMtn8h3GvMT=~hwYKM>%-6~1 zo@{c=-jaJMCd+tB_D5OduMk{LbbGfE`gYSBsm=vFd*})@M*Gq$<(Xp_jMR?C49Q$K zfGBSH$vRZ !I#q_iC}5^dln?nhobn;@w>aoHkdR&H2gvtu=IP^(!X>yRvg z+k`>=x~y~B9s!ES4~K+KLoMJ6B9Wv)_`7ld+PIr^9QYm_BxSJtU{>klO^zKcZ$7+P z)5%sUeVRlw=DGd))b&;KjXL%Q@U>}I*i$Md$FnY&ZQlFIV#_D#?WR4B`fg$EdtrCe zxXZBd`sxBY?nLJTDRFp!ghNf3C@CI0H5M))1(!8&d8Od2eOi4|Aw=J7zfQ8yO*bBs z;LtHnxAoV90wT5{DIM&x;@{e*BkSencZiBd=y9!46Hw;>14`p8@(?EvILUxh5gJ7t z=2y+9ww_=$NF%WJLRY9xGZSNU!` ~dXSTebQUrR4!w1iv# z%(-^3#gt&$5uK545&kW0#{`s7mq%t@nPoA``6_7E$;x7`X4I|*ODW1kzH^ipml;d@ z@m%+qsmWzr)p>QXak-+}01!}M)Wo%YeimJF$LmH;TcmKNNa$8)nXwk-i &fyD4x=`zoLYGz|}M3C0mMGkC6I1L2rDLNbrSc#(Jj2&~FZRsD?FyrkPvepJ{^J zWkiVeEUBLuf{v=#2 fBPY`v8OCYk)3dw9CR|>#rX}X|JC;4v3U}X z!vf=Iv)*sBQ(46c@+B%ekD~5nUY2E7n-(D#LX2A)l~DaW`|A3BEC-k6!pktoGEL8t z5{xIVbS$7~M`+uf6Hj5MU&D-M7|o5`<)_xBgf&9*ygRU%Cy1ddv5X6NmMz}~jHdu) zftMjWb}dXI=4&6wd9Yh~Os|Es;{w#r>Cs7ymP~cOCU(_0-= Bw70^5=LT!hCG>uqY9Wte^CP5~}h zJqyWFtLsQHpFrI>s(b#m&Jo<8vgg9tPj&;&{n%ApmBhKRv?jzMo4TF4&PJ8#0y>eI zW`wn>FoC{pAJtigvqDrKbS3B`gy*ejzVmv!#9M<#1uN$Ztp-Qrg2t*0& !|3XV!x=ko?AU-snhl zm}`lQ>;)%rC*;EWrIk6kdEPi!%B@vwx{`b8koR#<)0YA%Dvw6$EnG4bI9yx@bvED% zn}j%24YZH<&?IRBx}tww#`tNnM27P{dGlBDJKVw#XJ5XwUl%G93kDO?<5y9$3(~uB zh{KN<4{p`>fAdsyi-Ok w6?bpH~>Kx@O=8k0l*I%(Ep dfL-lywKOu6hJv4UaBIO >T)5w zMkAV9Qeoa8iwLi|XYyQz+vugEcJiXl8{$C=r-E1a4Ha6Zjaq+Zi%4EP$J7wG+L9xS z%Zlm!bsp*6T$I;|1Kl{r=&VG?fGGJM@d#J!&ARHQyD}d;HogC2`uL6c=2IzkDHmkI zvK^46&*T1x{0h6%VR0!-p|9_yxT@yUjyG@jJKkJA(aF^f@MG1pKVzcE{aB`V3eP|9 z0|OW~RdI}S=1H5D=*--Q&n NmuBle}ZY~T wtU|WJt35tP U^F&VJC|b_=Nme?y_XGw^ZP=tT+`D$Jwu-_<;UD|e zMICbG!}sooMn*aXez3iH*vRY>(5q9m_H$SG4ccKjKKW}Oymu)C(o_wIrtO+r5-y*6 ze!T0I>y;Q6MT@IDcTn zAeAeAnvM12DRbteF7R9{E2bG#s*PM=$0s$N)AA7y(G_CAc4x1MuG|pLGx^!nkul~L zL3GMWuRUqDb5?l#)5V_ftmZYsuR=26KDxiCdGk*|)qHzlvR_7!Wk} |KT*bI4=oFYDqeVmE;HaZDc-mU zS5juwZOu9LMs&w+z-a@ONJ)>UKN4J*Rc <= zm8t$hoS#@^qJdxRFDT(YLPByK5>H$!D!x;3$WS2~R8;6j)f4_k_tSZ6QVR>!#J;>Z zhf6E6nMQYN3)v-US7YY25g!l9%VS1+8yEa=RRmR}^mk-=EW@#Y4h-EQ&p}Nl@rQyr zx99JB6RrkPUGz)Q?B}X}5uASH;G@CFQtTC+_nU+C1mHicNSyolV|4pP@p;3W`#v^q zYVEDxMZ~CEiU!3ao01rRs%r7$u?+hcnneDiunCRXrh9Ll-&i|0ZnfQUL@wAjn=73< zXgnLEkf23RqQ1jrn?6^}4b^HMkL{Aemy8Fnml%&_LS3TwIlXyVfKpf $G3h2B9J|C)*1C#{IB=#_MK_K&JfyS7t}&_`drNh( zVjXgD?*3C`$JxDaadBIpJ2hBe3=-&2qeO=<$vEi1sZm|tB4%HT49rjy%|eZIUvbS? z-E)X%^gep-4xMpDdECipN;YtCPd|DbjEmdvt+8puEY%j`{}pPvBFEJYH@|mciw>*0 zx+v*=V)KIrn{&s*iZ> P7zUGAMQ-$-OqokE9%m8+X9y*=)oap zlw}&Xvqr1yPS^fM^_Nk!4Cqm5X0g3< m1W;f<4cZsq2(T176Y}@AtLUTy5Wz?Q`dm9)l}>i3ix|hfB}RPswGi{zTmo zUYbd;DZUbVEIUNjp!I=-)MoiBk8FMtkBIGyIIJB4XZ#4b@hzJovE>eMVPIQds3RDf zKpGly5||%tcWQ0!ix@5Cgycm^B(|o-rKiha>i5bRL>lKlbKy_|ELjQ2c+FV{b9Y=8 zY7?iu8~1ftili#O=Sm%BO6K6N3W95uU(L)wt1xPy;+kmjgcf(lLu =Lg9y$e0(zJ9Pi zR{E&zzRa=5Z>7IRC-?qJ%~msZj{Yku`YxtzZm#oT?hTc1TC?G)=KWncgIv7_nra1FwzsQD*6txG zW^ILfsa72Py2C)Qzof*XA??*ZxrMB)yP8V>08?cwE9?4H$sG5H053J2?vq}CZDsKh z&*8^7?+ndswmj9Rh|gQG=_|r}FR*L%)V_v9_P9jm8a^xA8(@7SG}vVS5qOi`9812d z?}e!;E}<}J3+5X#j{F2w
0ngSgJ%2P2Z|&lM(N?e=3E+Y2UP@x?4Y)wS4+iw@mTHlH$Y4c!L7@&db~H zjy}gVH|{)ot)Ezae4)GN*s%U9W#U(q6M?pGC}7(c#C+HA7^iC7u<^5E*`~?bw~YPI z70H`Sy72X{mZbw qMYB*F6q8!cJ6VIoetovbZ{mQZ8WR6$$!57GK!dlp(nTDRo zSDeq7Itw%0^>wm#UUuh=*R3f62r=Sa9dZjjZHH596q=^^r}gS^Z-fNv4pcbS{kCv@ z?7cV2UwV!qXeL9}_SyC9d>J~lalW-REA~Y7zPij4V<*l$&+IwbhJWeh=Tldapp%>1 z$Ym!A2G0VjD+k@N3#BBVK6LqgMRDbv0Yg6p%7bZ}tAy;1O1peJme~8(xnPmof1Ucp zqUy_^wFGl;LrUMsS~lCrj~p-r$&Ii6>&s?MC{^Gpeu*3~@H;W~1#AhU+y@xyQL1Vm z$3U(j$R%!6so%)IpUVe}Oa%EW!pkPx_SBHP0X6f8e#U-^Td6RW=3kJZ(O3_zWr-}Y z2tSSJ6|*Lzj4}R(ChKGN23|^edHHgdrZg|jB737eu-&TYyHb8ArK60Vfj0Is%k~1h zv`m-%yeZTMk(=eNv^mRM5r6vOcZK18Vy4sp*ADX*!`%9gve?}4_b`&@0R~}>2nJZj zG{e=-C~cudO;8W~yGZj>D?7D0HPQKbdKtIrpzvId?W4KxQ)|`&>6BKm Z>ONn_{dn!AR;uCe{L z3Je8?=bZNHoTa5@Zs+_RvXoA4{>rMSZw1(^M$@#lBV !G&;AAOM069>TIVGs=Ay-Yg8B7_7QM3jD&)XxzxyD64~4 zX>U|O20mxcA_ndG<#q7NUJ_`fkKYQw3ew-W%VGfQM&`gUzv()3)kS`0ArkY1-Cxdc z#d`rz0gAHt_5Gi-`%nYJ4uG2L iw1L^Qw35eR7E@Z4&Z~&W^6w8yxEyoJ^oLQV!Nn^yEq6p1CNLzl`vC z=cphh^YdnS!zJIVIfUESW_n|n+>Yqs-LOF*xN__64TSlAg+9M8@ZmNrf!>w4%S+GjY{Ru(yPIEN1^>b5eSjMD zRj~aEQ<3nOHBOJM7`SDv-9l73Ycc4%67t6{_$9)=`xEg+o42 zyZCPOMIblp_Aw#l+wRWXgPWZaP8q#-CzX;OYVCLO{m4%w|E|R!%vwoj_{-=E+5VV2 zwMF^Ou>a}?$GM3l`{_zgAgc|IPkA*mo7bc>X)QCcOG&GGsF~jQ|6XyaYS_NPP#_s^ z08ZcBhfPL3xCXeG)CF~43o0kJ%tS50yY*%<$optA@8vW%;1Lh8s&{QBrSl&p=+qg# zNebir+{(Pe^fshx#dqrDJs`7%V3)Vtdf(hHYE@a}cx3p;ZLew}8BJKJKop^??13F< zlfJ#C@$t`X-Cp9O)VFo7+LVyv_I=ElN^{Jw_o60;TDka4+FTQpbSvz0yrbeNk>L-< zKegp0yN5K5(2ov5w 8(ZyucB1Y|Oe0+h=-}BA?$e{MN{4s9 zf2(P|UzschzZO;FyZwcv#;@hEbD7v?MgQ~rIJGio8XwGR^0C#j;nX6E&9&+IW-^c5 zzQ)&bx*9hYP!5 m8OnPPyWSz ze G8!LbNk5@5oHn$ls>KdDzAu0y`|d~H=M^uO %~!v%pLV-z!HO GplNe>4!$ zB`tlxUQ<_RtaQalZcg!46ZQMx{)0(Aa 38ef$SU|1sPa?86% zSVUKu%P8mkzFEgHIm9)EM{vq582pbt> F(j&??e6IK<|5GugYN_YsPu5BH@00v~ zq$(EFZL+xpdjS?!4vwYPSvdwfNPWw#LZd#;4~cOFv7jX`ao)Tkn*QQ7=F7c~zMk zCgDyKR;X78`TU{#G4-DG?x>IpV_3P)XV1t-NOv~|k<#~Z^1+DvC-)tUMd(Q;N-~AS z)#D`&V$mfV!W8|~e6WbxoVM0iT@$e^rOj){Ppn+(WBDWEs^dD6BB_@qO=hPFz14Bt zL2!y(I&D^wGo6G?MosqYIj5F%#d{lO_veMDdb9Bfzb6)qqB=iGpAzsG>xF$&Y?qH) z^px=YdUmH~f*e{A?No7Ux(u6qKQwl9%e5QOmx62~Y^ac=(;C;$;2lY`UoQV|U7gsh z6`SqTZ9m5!Tt_TukH0@N-Tp52zGB 9;<37yLw_{{F2)j&zlu`Zci p&9vo$N4gM0mqwGyWe^iuHvpCo4AUE$k88%hx^PLr2Cz>6cO_8h@^xFwtnvk zq#rQ4w&K`U$Fgs~ ((5fPQdK>R@5aP-W5U@2 z^v$z^UC<) ;h zvzPxS4d=vqK B0vMT(V$Gb25Orr)JsO+)JpPW2|~mJ!?nltr-}}wS>c? zT {MT%)uLTp~PM> zqwk&(y6?PSWxaZM^T+rPorAsGS;1G2NEL2saAn$0y)TqBE1UX?+t&u-dvdpwMQ6pX zrV0FvaE1vu?hQ;m)HU1G3zewZJbn`L@JCkfiI|^poM+gh$XA3BAykc3=pj+lJ{Q_) zg}343&CK`MmmKHKvj}G11=CDe@V+xIg%lc@uj9C8oHIJ%bCuNwBGvmIrGE1hLdtzQ zdso9-V5&jgTK8)kOlRM3I?NCEr5agdwRXej eNARb%<&E$KHS z`;WW-dcAqy_o%4FXS%Cl&xHxam+Qy2#Qk8k>`eXEaWyV YP{_i7J!yjI@) zy;tz-7YV!N_A!%uu_zMv;Ml9aw||`(m8P6;S{&3UfMCc+``kZOM?XHZO>X7UzG8t) zMep$hOd+-#s(4B7Osu5hjW+>=-SR9Yvqy!QnpIiRJBEAQTn}BiEtOdUcmw}5c#nIv zzhH^?lAoFi>)B&J%H0>w7ij8f@9Nq$Y0y(#>M7 v;;rJv z614#GOvK6u4QwN>aDuNR1+fqJ^f=o%F0n=LX?o!aUH5vWpmO>Tkq%A#O1BVw%SI8x z?Z4uFlI%Bf>}8W;-AazW#}#hqSfO8}XLvD|9DgAX2``A$fi|7m^Vat=L1`UQFG!aJ zG_zsfKSH}cd5``}eZkt7sk-(+ RSJ%#7UTPdW^V72H5r*>Nm0%yI>dn1vfF}a7#R+Gz z`m%>+!uQn~iZ{$$(QVz2eRCg-ydX-%na1j=Z(7A;ormNeH*7h%MDw_#3J8|1t~iTD zFDm15l~A+R<$xrqltWr!8d{qLW_rJpvg3=6bTPRh+G|L6SEFwAUE4eDC3avm`oouB zxfSyo9D1OwO+6|R3x(_x7{z|T4d?^r4WBK0J*DZh8_ByFE@#spne7;O^Md5o)Js^L z*?lVVq`)}co+T%2?OCWLS*bWWOqP%eYDSja_0Kn|du@^_3CqyzKDqXK@FBKtYgO-D zRgbidmt8_!>;6?H!!UZvTH?}23EIJ_uGz%n GuVW-3mXMUbx&QrPS%F2tw zB7Yg4H$CqG*ORa^=<(P^a1nivj=GFb`mi b`YuP0Et^x5_yjL|-4b`~Ai7`*+p~*rDgJs3*>vmSfe~f=`=?2mVT7OG?kI z@(G3++a>zYONeIB`s$s#)9lGFYl e)q5s=px~ z{8}aYf=lN62^05yIFC(di zq<>#{?1zs2t5RjQW8nM9{u6_`<=Kxv?zplh&enTfM>`$bPCI(rrSq)G!H4@g8Yzqv zDlb)f5wGNe`du;DAyBy`YSm*(6{ZgP0{s$Z;`~P&D<)@so^Qq{ThxQTG8z}6|K<$3 zGo+>)QB~}5#vq0<7+A%^EQ9;Th1dZ^75bkfnV%f|U&;RirqGDB{k^a%i;>PyX}wcy zb3!!qa_awg^UkFQ Eg=Cq(R*qlG z$FIc?*%3^@+hMD%G+bSLTIc)}%^$;yq=CTa43EXXxG_}OB|Ntbn&31qqkX}RmqQ#N z4$3aF2L-DaW*Dlx0Kz~Dycztcgc;Wqi(0`VLP%n)jlVF}K*JGqG5GA~rt&|`*qSO? z_T~TmSwi$6Ows!{N|q48|5O0UIk6hj9X>E0fd2``wgwu~Lr4CF{U03v0BqF!FPeW~ z{|EYC%pzC>pl{<(F)_cEciDcK4YsaCSOr#%RH2vUIu{7Bk0{_ZG*cbv%FQ)?m?coo z!nA`N5vY3)LDXqkh~%sMKbg3bv#2y?aYd!L;yUE`yk-4#-v%nrbx7Uw#T75fT}(_% zlJ0ffaoL&gBd<4?I*v0$mf1w!B@L8oe$W&&XzfB;!wHxYAqFnM&}*DOKF&aKUaG0> z5tiCD(Kt)O_htDeYF(}EwIsUpoAoAo0Ad6M^IhTb-yXsP^qLGQYTVXkcIZE33Z?uB ztM4KCCUb`YIKLrS<|Ry_VQ%UG0q@ZpG~ACwl;%gl!D_57NDuX!*f^4*snPXHa&xN2 zJJWNlPZ!$W#1NmBi=oPrV*4x`d6#aHR6eOCY2FM>s&CaWUmZHf=@%>}F5Z!8fkAal z*AlLD&Ic_5%6y2Nmo}KZ{OH8Zp=89^%*0124Lm%40)B@_yf8})ZL+HyTJvQUkSes$ z?r20AZcO{9l3XY;zB42N6~#P7D$u}*5k<6&S+PXOvJ$a#0UFzfM6mX`!m3bgo0A$p z!!9Ns!wGPda#kpB39*7N>Cx?(PnLYs@B{FN9Mah3apK%<*!I6GVAv~e(O5g^o22;h zj1iplDL8V%i~()rqKNFd+!To-=@q~IOL}5S@uxnnY))w-geDIm DXZL_8VTBm!Wu?e(! z f=E5TKA%&6^Yuc#d@6T-xN*?YVqWLMbs6o$Y zO(awr<|G(WJ=rnX`=np4G=ITM6{gE@@8H%krrKss8+MrIkzb e^MV&ZT_}@Yh7fQ9^*?r6#^p^QO(saO&9j0-kpT zOwOhZ)9+g*r1YU8nl>9i^QN>?Cg9{JgF$IfyAFMJ%)ET_K#L}J+&9(~Ryot#{y9I0 z+Rln#>>{qj&^&Wf0&S(B7 {5oeunY&b0#;6~|PP3!a zDDN0879HFMHJ{FTN=M~6O}mT`?^+gN*=jz&3`@_etdgQpDAT>D$>WSWT9e;fFuwsq zEHCuht@*SQ`YF>4Pav2c0*Q_xW7>H tnA%nO3ko*yy`X9}`*v{fxhJP&w zY3w>*#Qy>!SR(kwd3Y?FI>f}C|Gvoc2 ENUO2ks9*X}SEv?Z6;$z5t4f;o?h?Vawmzz~jM zK4eF{(o!V0cK-4{u2jiXL#79IJY)lj`U-V~xlJ@!=E|?m<(v2+(gm%&gu>Fx#A4H! zYAm&k)k;r{K_E=0XBOTK%pPE<$)9(c=#t!B66s(on{xiZaW9PB2ZhaIZ^RWk_ev?4 zE}7I0EgQFwaK%kLX`c2{)#?6`HPt;Ue)ZX_j%{Hh>YN0O`lgTK<5QYwL*o_yFrA;u z=+Fs$UrjZgc0z877Y(OHQFE;|QOd!{V+j^M(Af Nm)y3D|%-!dN}1aEY-%tvg=0$dsAc9GWIv&EiBt!ensfX zTK3FTL;BG2kc3%RQTmcYrGa7$Pv|{t-yZZ?nnt<`>~(|$vPTJj(N}{LH=iJ-Z~r7l zYmW`@gn`iO5PQDDDACw4#<_I}y%0C_8H?J(6W>+zZ>1MN*oLFmQ8;al{sS%H9otBv zsmWJ9!dzSY1XGfIZxAQ!9#L63&6O5~)*^)L=g!F$xNmyzcsg8z5&eO-Ih3q_Tp{ z*of&;f5E9bFvr2qMkZ!-NLkf%7C2M5uwYkw{c_r}=k8}zVr+ucb)LZZpxxFLlU&o7 zY)2cl^wuXgqiroZh^u{2$SSm+wwFi1dtR@A#Xv)s|IVo&`C_8iKBvq;HCDo#=l{MU z5OgGT>QDY#_>60mExaw0Bx?LxbE?MuXs|>}fN)sv~tOn$shymP2_{yet%yoG5bp zZEe*l_hrRsn&|Ul!fm_Vfoz#99`w1Ctxo;c_Csrpa>1C}v%bPDngV8dD$u<_E52*R zF9Hq{HZ>d=uPJ)T>(q6pSYV_rEnHJsj?IN9Y|E@Oa}=G);U9I@wDy>HtdY`3SV33O zu=-nc;$B*7$DM=Ix!0rJel7ae+EkdU0`5NqXR@CWpNp&vpD~Tb2j?lpxbBd?Zt>CF z+GLNjG(IqLSxq$Xxm|FwlbU?zkc9U19xJ^0PB5ZOHS@oA+(AAkL>=78vC*@?raIDb zuH 0?8}MU>69oi-4^@u@2BYx1M8t(HQ99YsUKFBL|5dYMY|Huj60NeUGwFgEfwu^ zas>P3IbDfzryrH-Fv n|U(&PDE@nd#N(wQO&b66|Yi{tT7q zD09wj=_uQC9jz3jR7^!2$VSL!tjLH!kxmtwQdVeJT~*BG5mn~Nj3wvG6RZl?UyoRe zPWkm?4KT$+@8D 2zksh|9$~`}PuX7VaeWs-)ou&(2UP+pvZ$^qH%@ zR<&byh917pVyl;Dei!V#am5wS81${%nNQyNlhTD1KWcu5)%j~VsGc}HUE5Bf?Y7kv zM;suxFg_mR#kCKuE|`69c_@{$VwKx8cCI4fGF+@$ulDoR{LU{YP($Bdy07@c<;+`G zsc4fqD(uP#RioTuMd4;(;-j5VJqtC0+XyGgBpZQ}vkd3Jl?hS#9>Be<)JY|yPhz22 z^qgyOu@3CS@gX~Xj -q8H2zFavh!@z755GRpgNm>xZHt8V48VS{q+%m@`OX2AG0#RC==Kh6+b zdzwU5!(T2-r?+T*lro=Ef%_+-Mpgsif*rO8$TN&==^XWka~83eFjRcU+Qy_u=4{Mv z3q+kk!phA6D(-Fjm)Lu_w=Im0b;wEnd|EvYoZZfDus%U?LWuL*aD%qELDO=xuV6Qf z$ighWy=4Dd;uD%COozMtdi4a3KT)258xbsX>(m5uTRY02j3zobVZ;*n4~$yN+#wz` zql2D3^bNicham@&22}$d`on(aXLJ gBKagZ)GsbGLgJKqP6H)%nHpo~@v3rQyho z9oXhmh5W>y*rz(Yll`Zd-n50Z5gMSxaUNcV8$2XP@Ylo*>a#G_ytPwabNONhT2)Y@ zr8ae%$HF$3;s!OPG_@w)+m+#}D4=Pr_qOJ%3sK+)KeU%*J8)G|%i#5A2}Vv53LBg4 z2}LpLw9vq<9n{LpODHR!?#(q?!&QN$2YxJ|ox5r>1zN@c_Y~S#5|G3a#?~55@|jf` zkQB>#SpwE=1itrNileCV+`y!sAC*h>B4RdE0ln4yTJvy5tzPDb=clAluCaX7CIIy~ zpnNv1=doJ$Y8CN94{0HMV>PotG+tH;p5sG3__W~}vqxGfMk&-a9V%3B32;4d9daA2 z766y4)0A@jH9#LC0DYVPS?zF__Jdss23k;~4uKionvP}T*IC@)z6Hv6N(<7ii&beW zxE5-+hRf1w25uB^kwPugD6Q@FEt gt^K+B#$q z(N*geSTzj@utgE>sdrSWdubuWP>i2iSAEa`(fh=X+ay6WqxK)4ZcPOcg#?s>A|jg6 zqBX*=8*wSHY8Wh^cq~tUZz6jdtR^;4_GrSA-h$EyVH5aaAD-(>+1+t?k@pz+1~k z?&`zbX`#H7>E56rAmXa#QY@bkPfL%q{Jv2h3*U!ac$fG G zOCzWe1#BS;EPs&?SR2Spp=nB?1j%En{#CITcq|@h9=-5}aB!e9yC=x3*HU{bpV3Um zR0Gbj`f(jzUQ$`={(?l;SZyj%&xFUq{vOU9?*p%p<8^ws`b_&XsH1}$N(a_KUv+U~ zCTw*|?)U&{S%DDizl|@JWqJO54_0oJ7+wILJqcH;E~*;3&0TIO(@N~Bw3BUNbfU_& z+cNxk`4#37Hr^9v7kKIafigi&mUwze6(U002`iGcSAp-MCTkbuwe0nC(Zc}D9sTe$ zkLjz4ogiH3HR?xQ1RFwBE?&g%(+k(eUh$HRIn+`m!tx;_gx4X}^zRo_TEH7ECVWZs z@%OXtq|f+kZtkGB2ent-qUZPTLPhO|o^6BWJwCvJZV9+eQ%hVEYevq+W`kN&wT-2& ze2Fu?0&QKoC@pG>UKqs3krd0eDeT 7Rrp zQH?Z abd{+-DEx_h+CjVHBO5K^;I{AnCSa7pGiklDq8g zU*M)U(`(eRxdiz(2N-oE1%2Cr_Y-Ryq)A{;P(swy5_{+r;Ek^>dKwW#Lh#Y(An@*n zIVOSN99X{1>NeLBHGxHhQl^-dsD2_g!ZP&tWsO_cuB<5KWiL?3oiBkIG2;SgZ>i>$ zRo){~lZoxBKlit03Fb)tD=niue5KCnf=+J331}L>`K`J0NfVxkC;qZ5!HzF^`PblW zZs2ttjPUimw5n5l$C`Sfuf#_xnEg(s5`r;In^6sf1;cTc=6+=lkqe0_G)xaJ3-5J$ zd0yO=MbD2 +g!_Cp|oDiALgaOmBw?&2WMxoG%1s`8F9!AjF5{arKQZ}ySf7_y1KDu zn=Iz^1xzLO!O}igW??6iLOZz}LhQrF{FU@Itw-Fbu{FK^VLht)2zLH;(n22?WLPvX zYbr?-r}W_92(9BZEzMHzRJ-JM?%HZd;qtsh721=_mAbRmWOwMDmh2LO(4Xxki5hI5 z3xwU&f-f{AYh<*pzR ;Cx!!u8o{<9(`}@~AFGGgrr?2B$m~7|O((5c_$f?V(wt)m+;P rFdl?&3iT7YAOXYHwrZE?j7SbDh;k4~6Z^aT&VBg23V%EI# z(}?%bn`m>U{3*6OzuOZ|-3LfMJ~yjQm~aCd%BrCFdpgt8p6HP&V1BirTfn|@eEo|J z2$R (IBT{;jj$FM2&NN6sTBy1 zh?%RwY1=YdHKaDzc;~2?rAFE*NK|6-k&`77WiWV?XH}k}!Za@vwGmC+1xJuN;JO3~ z6&aW9U%6|9NniDZKO(4rQETk*B{Pln3KJWm!lnSTNZgpN)5bY}K8%7mgIV@meqReN zXSZ`StVb|w;i;7#aV;BA0VV@@)2&2=9rrLT_7Z{dy#r=Inc6%wZ6IcnJ8_(QogX@^ zCzK-J{zQ^Hc2+^NTGuMo!Q^;k6BZ3Z40E#VD}koWj1VHakPZKUyiLQ;u0uA{aaR7) zG<*)y3V4m*7qN|WbP*Hj2nu-xT*4oC;aW8vX@#wwfp&52H|jCr&>?K|f77>khuMO( zjT+bjZqk2i{0{^l87TTc$hwi)Y{4aHH^7Pfuu&Oavq927I6i?^aaP#x936h+{0oYT ztp^v7$w!QQ`JXaC7#|7f5T6i$i{CGRi{B`}dr;~>)kok3xV_vUCMfLS5{7WmS_*-t z-1JWtM+t<%5oVPplL5YwIN*`Kw@X+>5FVVZonHdSZ^6sSOLHc@gcUp7FE@s7(QzK9 z7>Ml-+N_;L4dSJCav9T{-<4dueAGlKj-&;rR%zy_U_o53ntLI4bTAYMe}qXoTT2on zF9o9cUm!jYE+Fm>!s?{6HB|@z1A_FxoUMRpd%1fc8rB!E@r@R%CGBT&e AeDw&5%v}f1AOHg^*3V1olA=D_=0NcYhL*Quuwbb?@-fp_AIi zw;nzYPcHb@GW73r2?69`Gs io;dLy1*5jmc`>!)Rit=&1+3!40n#jpcb@5K`S|qe6EfMGb;SSfL$g-S0o!O=HP+ zIy{}pb%^ykM4B85TZfEj+Rl?hPIHa6aQN6&ws_T{o21+xzCHz3sqgY zyu~?d(DY@xVuCfA*>3!B&OHEnT_wM1P`15!f_CeD-YsnYXUui@U*==+WAW1-zs_LV zX_(HU1u_S| 3nT3$PQV90SeliAHG0EZFnUifsI{3p?S*S>Ygl@PXDtHYPi zZzV`;@q*};uCD384;E>nzU62rB|7`Bm{cEM3gP+fiN(3c#xuvnQuC%OtqbOUX7^bQ zpLS5ov0iMmy9-rKue9 TDdik z&wZWW?n8c-dPSw6E70mbv;5X yWA>wv9NG{SV7=OXo+ `X4y>$IjZ@79r7*q%#C LQRXPHFSSW5Q1>Wu1g~Q7Nh9xq3Kv(m z6qu`Mxeh@w&;A8d(CK>C9h0wO;?;zYpXRh(H5bp7D~J6xlo7FHsa&Gp?)2lkGsA+O zIfIS~Z6ci6K@OE>6`l({;3V`HUQAXrBUC8{^FR}A6S~!3Rlxwf&RXMjwTP8H6ph&3 zEgveiqac8I2Clkjti124tg^%1>=T3}X2e8dBmGnMNb)Af{#bZf;)f4@>yThCtf+>f zmJ(RSM03z3F@#+zu^|tx!*aC@R$`3|j2fMz=d8YRI>xxUvB-D93Y_S_Y9?;1L;j@n zNOIr!<7oNdUEp=dDq BXM)V{U;9=z~lgGf{V>MgocP(v08@=4{{s+gz|O_b7JfH03JLs z&>opzy$4hm;?4B4N%MLeH5tbSXRA<6xV2cY#Sh2s{Lacp&y%=0>yT-)b%^Uagbon+ zuR|F8hUk10T_mm{=t@4D5|49M11~owaXZr(t)#(Q;218EZ3^mXTRUJDZ^Ty2npww2 z;7w*bn~(PdWV-uW9`+**DI%xgJjgnPtZ2qFS%+BQs=+rHC;UHv;3fD2J}^k>@m>~g z+zj!H9LNOLRzoS%6nlF|jAbiERE%Ojvi1QvOs&eDT8D%eRON`n3^}e;|F1UI{$+#g zFe^jq8%3)^2eP54;`P+$q4326fI~kN&mcK+;70)EaZG6*IaE{;*H!4qbALr(i=sG} z3F{CoBu9bR#M`=kWPB`1^n}3C&bVBX&qp<;0>~>AwS83%%o-H7>=15 sUZ0y!TXu$ZC*e*xVvi^FYcg-w(R6Ebo06KXMiLK zqKZJqt3JF{JF}+R5;Mf*xviT&0voB6Bs;l?Yo@N8LAu6FFa{HNf}E-Bq?JTP9P?;# z@6S#}@ED}bs=+X6sd62{Jjxl^bsBU6k6gOVb4GIhT8E4#F_W0_XOmb+p7xKQ2XFLQ z9?7z7np?S!@bq?n^!s3u*5Jx0&kMOUIcD8VessPxFP?pzlPgB5<&a+K=k2?l)65xZ zN@7~_uA1F{W8n8;(5F1gk;p^x#CY(P4q(nB)*-g*kVW`v#TgKG_=)4lagdxR(XA{T zIZ0z3((vxKK^@I1MwfSA@OQ#xOQqRx|A{>2ad8fEQhKa{x2u`ssg*yDU|9_`{szN? zN?Ph%hdh%dum(AP?~uceJmn^r8wt2t9(nvDauje;eM3TEJN^&=BqJArPK~XYVh1w> zs};|VUr<@Nn<8a `l>X_66J_UXfM+VAU8Px}3C^Om*T;;KX*tzdv84v5Lp zY g;esH;)e&qAb=SQPC>~OUNbD6+ob-HUIZ4nW6pjxJgMI)4CGJLW;RK z;y4F9z%m;E5q%T_`xh_!eH&Ww(@SwIKdasoB}`p7Ub^6O>U>$8BCy@Hg!tKM@8#yu ziPExr$bFBzNe!!&Xg8TZ#rg215zaui{(Yan&lUQXE^xxKg^zo$WdKEAR$YgTi!~Hy zi; ^*Ao$_F&2 w9E-$PTS^v(IbOK$yADasZ1#S@2$VkHW7VidnuwX1 zm}Z^XOeVj=#$W1=o*R$npqP=4JPo@{jw$)>zync0ybNeq8Ev6q$`XkOoC9MlzLV29 z!#jKP4~b_PbGMeOXh)h@hXAS;zl_}3KH6lU>m$0iIbKp( !=Ie~m|t6U z^A+~BYmWb+flxr?{^b1_Lrz#GkiHScb#C+II3Y3^^ktODJKT@A4&-^#$~&