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

/* 单方差 */
class OneVarianceMethod
{
    /* Method name 分析方法内部名称 */
    public static $name = 'OneVariance';

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

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

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

        $type       = 'number';
        $dataDesc   = $settings['data'];
        $sampleCol  = $settings['sampleCol'];
        $sampleNum  = $settings['sampleNum'];
        $sampleVar  = $settings['sampleVar'];
        $sampleStd  = $settings['sampleStd'];
        $hypo       = $settings['hypo'];
        $hypoVar    = $settings['hypoVar'];
        $hypoStd    = $settings['hypoStd'];
        $confidence = $settings['confidence'];
        $alterHypo  = ($hypo == 'standard' ? $settings['alterHypoStd'] : $settings['alterHypoVar']); // option value: lt|ne|gt

        $hypoVal     = ($hypo == 'standard' ? $hypoStd : $hypoVar);
        $sampleValue = ($dataDesc == 'standard' ? $sampleStd : $sampleVar);

        if($dataDesc == 'data')
        {
            $check = new checkData();
            $check->setDataList($dataframe->colsData($sampleCol), $dataframe->colsName($sampleCol), self::$settings['sampleCol']['validate']);

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

        $result = array();

        $name = $lang->sample;
        $type = $lang->std;
        if($dataDesc == 'data')
        {
            $names = array();
            foreach($sampleCol as $index)
            {
                $names[] = $dataframe->columns[$index];
            }
            $name = implode(',', $names);
        }
        if($dataDesc == 'variance') $type = $lang->variance;

        $oneVar = new OneVariance($dataframe, $confidence, $hypo, $hypoVal, $alterHypo);

        if($dataDesc == 'data') $oneVar->setData($sampleCol);
        if($dataDesc != 'data') $oneVar->setSummary($sampleNum, $dataDesc, $sampleValue);

        $desc = $oneVar->getDesc($dataDesc);

        $result[] = self::buildMethodResult($dataDesc, $name, $type);
        $result[] = self::buildDescResult($dataDesc, $confidence, $desc);
        if($hypo != 'false')
        {
            $test     = $oneVar->getTest();
            $result[] = self::buildTestResult($dataDesc, $test, $hypo, $hypoVal, $alterHypo);
        }

        return $result;
    }

    public static function buildMethodResult($dataDesc, $name, $type)
    {
        global $dasLang;
        $lang = $dasLang->oneVariance;

        $sigmaSign = $dataDesc == 'variance' ? 'σ²' : 'σ';

        $result = new stdclass();
        $result->title = $lang->method;
        $result->type = 'text';

        $result->data = new stdclass();
        $result->data->type = 'html';
        $result->data->content  = sprintf($lang->sampleInfo, $sigmaSign, $name, $type);
        $result->data->content .= $dataDesc == 'data' ? $lang->continuousInfo : $lang->summaryInfo;
        $result->data->content .= $lang->chisqInfo;

        return $result;
    }

    public static function buildDescResult($dataDesc, $cl, $data)
    {
        global $dasLang;
        $lang = $dasLang->oneVariance;

        $sigmaSign = $dataDesc == 'variance' ? 'σ²' : 'σ';

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

        $result->data = new stdclass();
        $result->data->columns = array();
        if($dataDesc == 'data') $result->data->columns[] = array('label' => $lang->variable, 'type' => 'text');
        $result->data->columns[] = array('label' => $lang->N, 'type' => 'number');
        $result->data->columns[] = array('label' => $lang->std, 'type' => 'number');
        $result->data->columns[] = array('label' => $lang->variance, 'type' => 'number');
        if($dataDesc == 'data') $result->data->columns[] = array('label' => sprintf($lang->bonettCI, $sigmaSign, $cl), 'type' => 'text');
        $result->data->columns[] = array('label' => sprintf($lang->chisqCI, $sigmaSign, $cl), 'type' => 'text');

        $result->data->data = array();

        foreach($data as $item)
        {
            $arr = array();
            if($dataDesc == 'data') $arr[] = $item->variable;
            $arr[] = $item->N;
            $arr[] = $item->std;
            $arr[] = $item->variance;
            if($dataDesc == 'data') $arr[] = $item->bonettCI;
            $arr[] = $item->chisqCI;

            $result->data->data[] = $arr;
        }

        return $result;
    }

    public static function buildTestResult($dataDesc, $data, $hypo, $hypoVal, $alterHypo)
    {
        global $dasLang;
        $lang = $dasLang->oneVariance;

        $hypoSign  = array('lt' => '<', 'ne' => '≠', 'gt' => '>');
        $sigmaSign = $hypo == 'variance' ? 'σ²' : 'σ';

        $result = new stdclass();
        $result->title = $lang->hypoText;
        $result->type = 'table';
        $result->desc = sprintf($lang->testDesc, $sigmaSign, $hypoVal, $sigmaSign, $hypoSign[$alterHypo], $hypoVal);

        $result->data = new stdclass();
        $result->data->columns = array();
        if($dataDesc == 'data') $result->data->columns[] = array('label' => $lang->variable, 'type' => 'text');
        $result->data->columns[] = array('label' => $lang->method, 'type' => 'text');
        $result->data->columns[] = array('label' => $lang->testStatistic, 'type' => 'number');
        $result->data->columns[] = array('label' => $lang->freedom, 'type' => 'number');
        $result->data->columns[] = array('label' => $lang->p, 'type' => 'number');

        $result->data->data = array();

        foreach($data as $item)
        {
            $arr = array();
            if($dataDesc == 'data') $arr[] = $item->variable;
            $arr[] = $lang->testMethod[$item->method];
            $arr[] = $item->test;
            $arr[] = $item->freedom;
            $arr[] = $item->p;

            $result->data->data[] = $arr;
        }

        return $result;
    }

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

        /* Basic settings */
        self::$settings['data']         = array('name' => 'data',         'label' => $lang->data);
        self::$settings['sampleCol']    = array('name' => 'sampleCol',    'label' => $lang->sampleCol,       'required' => true);
        self::$settings['sampleNum']    = array('name' => 'sampleNum',    'label' => $lang->sampleNum,       'required' => true);
        self::$settings['sampleVar']    = array('name' => 'sampleVar',    'label' => $lang->sampleVar,       'required' => true);
        self::$settings['sampleStd']    = array('name' => 'sampleStd',    'label' => $lang->sampleStd,       'required' => true);
        self::$settings['hypo']         = array('name' => 'hypo',         'label' => $lang->hypo);
        self::$settings['hypoVar']      = array('name' => 'hypoVar',      'label' => $lang->hypoVar,         'required' => true);
        self::$settings['hypoStd']      = array('name' => 'hypoStd',      'label' => $lang->hypoStd,         'required' => true);
        self::$settings['confidence']   = array('name' => 'confidence',   'label' => $lang->confidence,      'required' => true);
        self::$settings['alterHypoVar'] = array('name' => 'alterHypoVar', 'label' => $lang->alternativeHypo, 'required' => true);
        self::$settings['alterHypoStd'] = array('name' => 'alterHypoStd', 'label' => $lang->alternativeHypo, 'required' => true);

        /* Type settings */
        self::$settings['data']         += array('type' => 'enum', 'enumOptions' => $lang->dataEnum, 'defaultValue' => 'data');
        self::$settings['sampleCol']    += array('type' => 'list', 'listType' => 'column', 'columnType' => 'number');
        self::$settings['sampleNum']    += array('type' => 'number', 'columnType' => 'number');
        self::$settings['sampleVar']    += array('type' => 'number', 'columnType' => 'number');
        self::$settings['sampleStd']    += array('type' => 'number', 'columnType' => 'number');
        self::$settings['hypo']         += array('type' => 'enum', 'enumOptions' => $lang->hypoEnum, 'columnType' => 'any', 'defaultValue' => 'false');
        self::$settings['hypoVar']      += array('type' => 'number');
        self::$settings['hypoStd']      += array('type' => 'number');
        self::$settings['confidence']   += array('type' => 'number', 'defaultValue' => 95);
        self::$settings['alterHypoVar'] += array('type' => 'enum', 'ui' => 'select',  'enumOptions' => $lang->alterHypoVarEnum, 'defaultValue' => 'ne');
        self::$settings['alterHypoStd'] += array('type' => 'enum', 'ui' => 'select', 'enumOptions' => $lang->alterHypoStdEnum, 'defaultValue' => 'ne');

        /* Limit settings */
        self::$settings['sampleCol']    += array('conditions' => array('data' => 'data'), 'columnType' => 'number');
        self::$settings['sampleNum']    += array('conditions' => array(array('data' => 'variance'), array('data' => 'standard')), 'min' => 2, 'max' => 100000000);
        self::$settings['sampleVar']    += array('conditions' => array('data' => 'variance'), 'min' => 0, 'max' => 100000000);
        self::$settings['sampleStd']    += array('conditions' => array('data' => 'standard'), 'min' => 0, 'max' => 100000000);
        self::$settings['hypoVar']      += array('conditions' => array('hypo' => 'variance'), 'min' => 0.0001, 'max' => 99999999);
        self::$settings['hypoStd']      += array('conditions' => array('hypo' => 'standard'), 'min' => 0.0001, 'max' => 99999999);
        self::$settings['confidence']   += array('pattern' => "/^[\+\-]?[\d]+(\.[\d]+)?$/", 'error' => $lang->errorConfidence, 'min' => 0.0001, 'max' => 99.9999);
        self::$settings['alterHypoVar'] += array('conditions' => array(array('hypo' => 'false'), array('hypo' => 'variance')));
        self::$settings['alterHypoStd'] += array('conditions' => array('hypo' => 'standard'));

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

        /* More settings */
        self::$settings['hypo']         += array('paramType' => 'more');
        self::$settings['hypoVar']      += array('paramType' => 'more');
        self::$settings['hypoStd']      += array('paramType' => 'more');
        self::$settings['confidence']   += array('paramType' => 'more');
        self::$settings['alterHypoVar'] += array('paramType' => 'more');
        self::$settings['alterHypoStd'] += array('paramType' => 'more');

        /* Data validate */
        self::$settings['sampleCol'] += array('validate' => array('continuous', 'number', 'notCommon', 'N >= 2'));

        return self::$settings;
    }

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

        //return self::$config;
    }
}
