<?php
require_once LIB_ROOT . '/dataframe/hypothesis/proportion2.php';
require_once LIB_ROOT . '/dataframe/checkdata.php';
require_once LIB_ROOT . '/dataframe/validatedata.php';

/* proportion2 控制图 */
class proportion2Method
{
    /* Method name 分析方法内部名称 */
    public static $name = 'Proportion2';

    /* Method settings 方法设置参数定义 */
    public static $settings = array();

    /* Diagram config 图表配置项 */
    public static $config = array();

    /* Callback for basic hypothesis method 基本量统计计算回调函数 */
    public static function func($dataframe, $settings)
    {
        global $dasLang;
        global $lang;
        global $app;

        $result = array();

        $dataDesc       = $settings['data'];
        $sampleS        = $settings['sampleS'];
        $sampleID       = $settings['sampleID'];
        $sample1        = $settings['sample1'];
        $sample2        = $settings['sample2'];
        $sample1Event   = $settings['sample1Event'];
        $sample1Sample  = $settings['sample1Sample'];
        $sample2Event   = $settings['sample2Event'];
        $sample2Sample  = $settings['sample2Sample'];
        $testMethod     = $settings['testMethod'];
        $deviation      = $settings['deviation'];
        $confidence     = $settings['confidence'];
        $alterHypo      = $settings['alternativeHypo'];


        if($testMethod == 'merge' and $deviation !== 0) return array('result' => 'fail', 'message' => $dasLang->proportion2->wrongDeviation);

        if($dataDesc == 'inSameCol')
        {
            $check = new checkData();
            $check->setData($dataframe->colData($sampleS), $dataframe->columns[$sampleS], self::$settings['sampleS']['validate']);
            $check->setData($dataframe->colData($sampleID), $dataframe->columns[$sampleID], self::$settings['sampleID']['validate']);

            $checkRes = $check->check();
            if(is_string($checkRes)) return ValidateData::result($checkRes);

            $sliceDF = $dataframe->sliceDataframe($dataframe, array($sampleS, $sampleID), 'any');
            $C1      = $sliceDF->columns[$sampleS];
            $C2      = $sliceDF->columns[$sampleID];

            $column1Data = $sliceDF->col($sampleS)->data;
            $column2Data = $sliceDF->col($sampleID)->data;
            list($success1, $success2, $fail2, $eve1, $eve2, $sam1, $sam2) = Proportion2::inSameColData($column1Data, $column2Data);
            $methodContent = sprintf($dasLang->proportion2->methodDesc[$dataDesc], $C1, $success1, $C1, $success1, $C2, $fail2, $C1, $success1, $C2, $success2);
        }

        if($dataDesc == 'notSameCol')
        {
            $check = new checkData();
            $check->setData($dataframe->colData($sample1), $dataframe->columns[$sample1], self::$settings['sample1']['validate']);
            $check->setData($dataframe->colData($sample2), $dataframe->columns[$sample2], self::$settings['sample2']['validate']);

            $checkRes = $check->check();
            if(is_string($checkRes)) return ValidateData::result($checkRes);

            $allData = array_merge($dataframe->col($sample1, 'nopercentstring')->notNull(), $dataframe->col($sample2, 'nopercentstring')->notNull());
            /* 如果这两行事件的总和大于2：请选择有效列，样本1和样本2只能包含2种事件以内的样本列 */
            if(count(array_count_values($allData)) >= 2) return array('result' => 'fail', 'message' => $dasLang->proportion2->errorEventCount);

            $sliceDF = $dataframe->sliceDataframe($dataframe, array($sample1, $sample2), 'any');
            $C1      = $sliceDF->columns[$sample1];
            $C2      = $sliceDF->columns[$sample2];

            $column1Data  = $sliceDF->col($sample1, 'nopercentstring')->notNull();
            $column2Data  = $sliceDF->col($sample2, 'nopercentstring')->notNull();

            list($success, $fail, $eve1, $eve2, $sam1, $sam2) = Proportion2::notSameColData($column1Data, $column2Data);
            $methodContent = sprintf($dasLang->proportion2->methodDesc[$dataDesc], $success, $C1, $success, $C2, $success);
        }

        if($dataDesc == 'summary')
        {
            $C1 = $dasLang->proportion2->sam1;
            $C2 = $dasLang->proportion2->sam2;

            $sam1 = $sample1Sample;
            $eve1 = $sample1Event;
            $sam2 = $sample2Sample;
            $eve2 = $sample2Event;

            $methodContent = sprintf($dasLang->proportion2->methodDesc[$dataDesc], $dasLang->proportion2->sam1, $dasLang->proportion2->eve, $dasLang->proportion2->sam1, $dasLang->proportion2->eve);
        }

        $proportion = new Proportion2($dataframe, $eve1, $eve2, $sam1, $sam2);
        $describe   = $proportion->describe();
        $CI         = $proportion->CI($confidence);
        $normalTest = $proportion->normalTest($alterHypo, $testMethod, $deviation);
        //$fisherTest = $proportion->fisherTest($alterHypo, $testMethod, $deviation);
        $desc       = sprintf($dasLang->proportion2->testDesc, $deviation, $dasLang->proportion2->convert[$alterHypo], $deviation);

        $result[] = self::buildDescResult($C1, $C2, $describe);
        $result[] = self::buildMethodResult($methodContent);
        $result[] = self::buildCIResult($describe, $CI, $confidence);
        $result[] = self::buildTestResult($normalTest, $desc);

        return $result;
    }

    public static function buildDescResult($C1, $C2, $describe)
    {
        global $dasLang;
        $lang = $dasLang->proportion2;

        $c1Data = $describe->desc1;
        $c2Data = $describe->desc2;

        array_unshift($c1Data, $C1);
        array_unshift($c2Data, $C2);

        $result = new stdclass();
        $result->type  = 'table';
        $result->title = $lang->desc;

        $result->data = array();
        $result->data['data'] = array($c1Data, $c2Data);

        $columns   = array();
        $columns[] = array('label' => $C2, 'type' => 'text');
        $columns[] = array('label' => $lang->sam, 'type' => 'number');
        $columns[] = array('label' => $lang->eve, 'type' => 'number');
        $columns[] = array('label' => $lang->p, 'type' => 'number');

        $result->data['columns'] = $columns;

        return $result;
    }

    public static function buildMethodResult($content)
    {
        global $dasLang;

        $result        = new stdclass();
        $result->type  = 'text';
        $result->title = $dasLang->proportion2->method;
        $result->data  = array('content' => $content);

        return $result;
    }

    public static function buildCIResult($describe, $ci, $confidence)
    {
        global $dasLang;

        $data   = array();
        $data[] = $describe->desc1[2] - $describe->desc2[2];
        $data[] = '(' . $ci[0] . ', ' . $ci[1] . ')';

        $result        = new stdclass();
        $result->type  = 'table';
        $result->title = $dasLang->proportion2->deviationES;

        $result->data = array();
        $result->data['data'] = array($data);

        $columns   = array();
        $columns[] = array('label' => $dasLang->proportion2->deviation, 'type' => 'text');
        $columns[] = array('label' => sprintf($dasLang->proportion2->deviationCI, $confidence . '%'), 'type' => 'number');

        $result->data['columns'] = $columns;

        return $result;
    }

    public static function buildTestResult($normalTest, $desc)
    {
        global $dasLang;
        $lang = $dasLang->proportion2;

        $data   = array();
        $data[] = array($lang->normality, $normalTest[0], $normalTest[1]);
        //$data[] = array($lang->fisher, null, $fisherTest);

        $result        = new stdclass();
        $result->type  = 'table';
        $result->title = $lang->test;

        $result->data = array();
        $result->data['data'] = $data;

        $columns   = array();
        $columns[] = array('label' => $lang->method, 'type' => 'text');
        $columns[] = array('label' => $lang->zValue, 'type' => 'number');
        $columns[] = array('label' => $lang->pValue, 'type' => 'number');

        $result->data['columns'] = $columns;
        $result->desc            = $desc;

        return $result;
    }

    public static function checkData($dataframe, $dataDesc, $col1, $col2, $col3, $col4)
    {
        global $dasLang;
        $lang = $dasLang->proportion2;

        if($dataDesc == 'summary')
        {
            return array('result' => 'success');
        }
        elseif($dataDesc == 'inSameCol')
        {
            $sliceDF = $dataframe->sliceDataframe($dataframe, array($col1, $col2), 'any');

            $check  = checkNullColumns($sliceDF, array($col1, $col2), $dasLang->common->errorLine);
            if($check['result'] == 'fail') return $check;

            $column1 = $sliceDF->col($col1);
            $column2 = $sliceDF->col($col2);
            $length1 = $sliceDF->getDataLength($column1->data);
            $length2 = $sliceDF->getDataLength($column2->data);
            if($length1 != $length2) return array('result' => 'fail', 'message' => $lang->errorEventCount);

            /* 分组列必须只存在两个可区分的下标 */
            if(count(array_count_values($column2->notNull())) != 2) return array('result' => 'fail', 'message' => $lang->errorEventSam2);
        }
        elseif($dataDesc == 'notSameCol')
        {
            $sliceDF = $dataframe->sliceDataframe($dataframe, array($col3, $col4), 'any');

            $check  = checkNullColumns($sliceDF, array($col3, $col4), $dasLang->common->errorLine);
            if($check['result'] == 'fail') return $check;

            $column3 = $sliceDF->col($col3);
            $column4 = $sliceDF->col($col4);

            $allData = array_merge($column3->notNull(), $column4->notNull());
            /* 如果这两行事件的总和不是2：请选择有效列，样本1和样本2只能包含2种事件以内的样本列 */
            if(count(array_count_values($allData)) != 2) return array('result' => 'fail', 'message' => $lang->errorEventCount);
        }

    }

    /**
     * Get settings.
     *
     * @param object $lang
     * @access public
     * @return object
     */
    public static function getSettings()
    {
        global $dasLang;
        $lang = $dasLang->proportion2;

        /* Basic settings */
        self::$settings['data']            = array('name' => 'data',            'label' => $lang->data);
        self::$settings['sampleS']         = array('name' => 'sampleS',         'label' => $lang->sampleS,         'required' => true);
        self::$settings['sampleID']        = array('name' => 'sampleID',        'label' => $lang->sampleID,        'required' => true);
        self::$settings['sample1']         = array('name' => 'sample1',         'label' => $lang->sample1,         'required' => true);
        self::$settings['sample2']         = array('name' => 'sample2',         'label' => $lang->sample2,         'required' => true);
        self::$settings['sample1Event']    = array('name' => 'sample1Event',    'label' => $lang->sample1Test,     'required' => true);
        self::$settings['sample1Sample']   = array('name' => 'sample1Sample',   'label' => $lang->sample1Event,    'required' => true);
        self::$settings['sample2Event']    = array('name' => 'sample2Event',    'label' => $lang->sample2Test,     'required' => true);
        self::$settings['sample2Sample']   = array('name' => 'sample2Sample',   'label' => $lang->sample2Event,    'required' => true);
        self::$settings['testMethod']      = array('name' => 'testMethod',      'label' => $lang->method);
        self::$settings['deviation']       = array('name' => 'deviation',       'label' => $lang->deviation,       'required' => true);
        self::$settings['confidence']      = array('name' => 'confidence',      'label' => $lang->confidence,      'required' => true);
        self::$settings['alternativeHypo'] = array('name' => 'alternativeHypo', 'label' => $lang->alternativeHypo, 'required' => true);

        /* Type settings */
        self::$settings['data']            += array('type' => 'enum', 'enumOptions' => array('inSameCol' => $lang->inSameCol, 'notSameCol' => $lang->notSameCol, 'summary' => $lang->summary), 'defaultValue' => 'inSameCol');
        self::$settings['sampleS']         += array('type' => 'column', 'listType' => 'column', 'columnType' => 'number');
        self::$settings['sampleID']        += array('type' => 'column', 'listType' => 'column', 'columnType' => 'number');
        self::$settings['sample1']         += array('type' => 'column', 'listType' => 'column', 'columnType' => 'number');
        self::$settings['sample2']         += array('type' => 'column', 'listType' => 'column', 'columnType' => 'number');
        self::$settings['sample1Event']    += array('type' => 'number', 'columnType' => 'number');
        self::$settings['sample1Sample']   += array('type' => 'number', 'columnType' => 'number');
        self::$settings['sample2Event']    += array('type' => 'number', 'columnType' => 'number');
        self::$settings['sample2Sample']   += array('type' => 'number', 'columnType' => 'number');
        self::$settings['testMethod']      += array('type' => 'enum', 'enumOptions' => $lang->testMethod, 'defaultValue' => 's');
        self::$settings['deviation']       += array('type' => 'number', 'defaultValue' => 0);
        self::$settings['confidence']      += array('type' => 'number', 'defaultValue' => 95);
        self::$settings['alternativeHypo'] += array('type' => 'enum', 'ui' => 'select', 'enumOptions' => $lang->alternativeHypoEnum, 'defaultValue' => 'ne');

        /* Limit settings */
        self::$settings['sampleS']         += array('conditions' => array('data' => 'inSameCol'));
        self::$settings['sampleID']        += array('conditions' => array('data' => 'inSameCol'));
        self::$settings['sample1']         += array('conditions' => array('data' => 'notSameCol'));
        self::$settings['sample2']         += array('conditions' => array('data' => 'notSameCol'));
        self::$settings['sample1Event']    += array('conditions' => array('data' => 'summary'), 'pattern' => "/^[1-9]([0-9]{1,7})?$/", 'min' => 0.999999, 'error' => $lang->errorSample);
        self::$settings['sample1Sample']   += array('conditions' => array('data' => 'summary'), 'pattern' => "/^[1-9]([0-9]{1,7})?$/", 'min' => 0.999999, 'error' => $lang->errorSample, 'gt' => 'sample1Event');
        self::$settings['sample2Event']    += array('conditions' => array('data' => 'summary'), 'pattern' => "/^[1-9]([0-9]{1,7})?$/", 'min' => 0.999999, 'error' => $lang->errorSample);
        self::$settings['sample2Sample']   += array('conditions' => array('data' => 'summary'), 'pattern' => "/^[1-9]([0-9]{1,7})?$/", 'min' => 0.999999, 'error' => $lang->errorSample, 'gt' => 'sample2Event');
        self::$settings['deviation']       += array('pattern' => "/^[\+\-]?[\d]+(\.[\d]+)?$/", 'min' => -0.9999, 'max' => 0.9999, 'error' => $lang->errorDeviation);
        self::$settings['confidence']      += array('pattern' => "/^[\+\-]?[\d]+(\.[\d]+)?$/", 'error' => $lang->errorConfidence, 'min' => 0.000101, 'max' => 99.999899);

        /* Col grid settings */
        self::$settings['data']            += array('col' => 4);
        self::$settings['testMethod']      += array('col' => 4);

        /* More settings */
        self::$settings['testMethod']      += array('paramType' => 'more');
        self::$settings['deviation']       += array('paramType' => 'more');
        self::$settings['confidence']      += array('paramType' => 'more');
        self::$settings['alternativeHypo'] += array('paramType' => 'more');

        /* Data validate */
        self::$settings['sampleS']  += array('validate' => array('continuous', 'columnUnique <= 2', 'rowEqual'));
        self::$settings['sampleID'] += array('validate' => array('continuous', 'columnUnique == 2', 'rowEqual'));
        self::$settings['sample1']  += array('validate' => array('continuous', 'unionUnique <= 2'));
        self::$settings['sample2']  += array('validate' => array('continuous', 'unionUnique <= 2'));

        return self::$settings;
    }

    /**
     * Get config.
     *
     * @access public
     * @return object
     */
    public static function getConfig()
    {
        global $dasLang;
        $lang = $dasLang->config;

        //return self::$config;
    }
}
