<?php
require_once LIB_ROOT . '/dataframe/spc/xBarS.php';
require_once LIB_ROOT . '/dataframe/checkdata.php';
require_once LIB_ROOT . '/dataframe/validatedata.php';
require_once 'spc.php';

/* Xbar-S 控制图 */
class XbarSMethod
{
    /* Method name 分析方法内部名称 */
    public static $name = 'Xbar-S';

    /* 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;
        global $lang;

        $result = array();

        $type      = self::columnType('var');
        $multiple  = XBarS::formatMultiple($settings['multiple']);
        $xRef      = XBarS::formatReference($settings['xRef']);
        $sRef      = XBarS::formatReference($settings['sRef']);
        $vars      = $settings['var'];
        $varGroups = $settings['varGroup'];
        $sub       = $settings['sub'];
        $group     = $settings['group'];
        $groupNum  = $settings['groupNum'];
        $groupCol  = $settings['groupCol'];
        $σ         = $settings['sd'];
        $mean      = $settings['mean'];
        $tests     = isset($settings['tests']) ? $settings['tests'] : '';

        if($group == 'false')
        {
            if($sub == 'column')
            {
                $check = new checkData();
                $check->setDataList($dataframe->colsData($varGroups), $dataframe->colsName($varGroups), self::$settings['varGroup']['validate']);
                $check->setData($dataframe->colData($groupCol), $dataframe->columns[$groupCol], self::$settings['groupCol']['validate']);

                $checkRes = $check->check();
                if(is_string($checkRes)) return ValidateData::result($checkRes);
            }
            else
            {
                $check = new checkData();
                $check->setDataList($dataframe->colsData($varGroups), $dataframe->colsName($varGroups), self::$settings['varGroup']['validate']);

                $checkRes = $check->check();
                if(is_string($checkRes)) return ValidateData::result($checkRes);
            }
        }
        else
        {
            $check = new checkData();
            $check->setDataList($dataframe->colsData($vars), $dataframe->colsName($vars), self::$settings['var']['validate']);

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

        $charts  = array($vars);
        $cloneDF = clone($dataframe);
        $xbars   = new XBarS($dataframe);

        /* Not group situation. */
        if($group == 'false') $charts = $xbars->groupData($varGroups, $sub, $groupNum, $groupCol);

        foreach($charts as $key => $chart)
        {
            if($sub == 'column' and count($chart) < 2) return array('result' => 'fail', 'message' => $dasLang->common->errorRowEqual);

            $param      = $group == 'false' ? $varGroups[$key] : $vars;
            $textResult = $dataframe->getTextResult($cloneDF->getChartTitle($param, $lang->perfanalysis->methods->control['XbarS']));
            $textResult->name     = 'var' . ($group == 'false' ? $varGroups[$key] : 'group');
            $textResult->children = 4;

            /* Xbar Chart */
            $iTitle   = $cloneDF->getChartTitle($param, $dasLang->XbarS->sampleMean);
            $iResult  = self::buildXbarChartResult($dataframe, $chart, $multiple, $mean, $σ, $iTitle, $xRef, $tests);

            /* S Chart  */
            $mrTitle  = $cloneDF->getChartTitle($param, $dasLang->XbarS->sampleSD);
            $mrResult = self::buildSChartResult($dataframe, $chart, $multiple, $σ, $mrTitle, $sRef, $tests);

            if(!empty($iResult) and !empty($mrResult))
            {
                $result[] = $textResult;
            }
            if(!empty($iResult))
            {
                $result[] = $iResult;
                if(!empty($tests) && isset($iResult->tests))
                {
                    $result[] = SPC::buildTestsResult($iResult->tests, $dasLang->XbarS->sampleMean, $param);
                    unset($iResult->tests);
                }
            }
            if(!empty($mrResult))
            {
                $result[] = $mrResult;
                if(!empty($tests) && isset($mrResult->tests))
                {
                    $result[] = SPC::buildTestsResult($mrResult->tests, $dasLang->XbarS->sampleSD, $param);
                    unset($mrResult->tests);
                }
            }
        }

        return $result;
    }

    public static function buildXbarChartResult($dataframe, $vars, $multiple, $mean, $σ, $title, $ref, $tests = '')
    {
        global $dasLang;
        $lang = $dasLang->XbarS;

        $type            = 'number';
        $meanKey         = 'meanSub';

        $sliceDF  = $dataframe->sliceDataframe($dataframe, $vars, $type);
        $xbars    = new XBarS($sliceDF);
        $data     = $sliceDF->cols($vars, $type);

        foreach($data as $item)
        {
            if($item->numCount < 1) return array();
        }

        $rowMean = $sliceDF->rowMean($vars, $meanKey);
        $xBar    = is_numeric($mean) ? $mean : $xbars->xBar($vars, $type);

        if(!is_numeric($σ)) $σ = $xbars->sigma($vars, $type);

        /* UCL LCL */
        $limit = $xbars->xBarLimit($vars, $xBar, $σ, $multiple);

        /* Std ULCLs */
        $stdLimit = $xbars->xBarLimit($vars, $xBar, $σ, array(1,2,3));
        $stdULCLs = $stdLimit->SLs;
        $stdULCLs['C'] = $stdLimit->CL;

        $param = new stdclass();

        $param->lang         = $lang;
        $param->points       = $rowMean->data;
        $param->name         = $sliceDF->columns[$meanKey];
        $param->lineBegin    = 0;
        $param->lineEnd      = count($param->points) - 1;
        $param->CL           = $xBar;
        $param->ULCLs        = $limit->SLs;
        $param->title        = $title;
        $param->xTitle       = $lang->sample;
        $param->yTitle       = $lang->sampleMean;
        $param->testsResults = SPC::checkTestsRules($rowMean->data, $stdULCLs, $tests);
        $param->ref          = $ref;

        return SPC::buildChartResult($param);
    }

    public static function buildSChartResult($dataframe, $vars, $multiple, $σ, $title, $ref, $tests = '')
    {
        global $dasLang;
        $lang = $dasLang->XbarS;

        $type            = 'number';
        $defaultMultiple = 3;
        $sdKey           = 'sdSub';

        $sliceDF  = $dataframe->sliceDataframe($dataframe, $vars, $type);
        $xbars    = new XBarS($sliceDF);
        $data     = $sliceDF->cols($vars, $type);
        foreach($data as $item)
        {
            if($item->numCount < 1) return array();
        }

        $rowSD = $sliceDF->rowSD($vars, $sdKey);

        if(!is_numeric($σ)) $σ = $xbars->sigma($vars, $type);

        /* UCL LCL */
        $limit = $xbars->sLimit($vars, $σ, $multiple);

        /* Std ULCLs */
        $stdLimit = $xbars->sLimit($vars, $σ, array(1,2,3));
        $stdULCLs = $stdLimit->SLs;
        $stdULCLs['C'] = $stdLimit->CL;

        $param = new stdclass();

        $param->lang         = $lang;
        $param->points       = $rowSD->data;
        $param->name         = $sliceDF->columns[$sdKey];
        $param->lineBegin    = 0;
        $param->lineEnd      = count($param->points) - 1;
        $param->CL           = $limit->CL;
        $param->ULCLs        = $limit->SLs;
        $param->title        = $title;
        $param->xTitle       = $lang->sample;
        $param->yTitle       = $lang->sampleSD;
        $param->testsResults = SPC::checkTestsRules($rowSD->data, $stdULCLs, $tests);
        $param->ref          = $ref;

        return SPC::buildChartResult($param);
    }

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

        /* Basic settings */
        self::$settings['group']    = array('name' => 'group',    'label' => $lang->group);
        self::$settings['var']      = array('name' => 'var',      'label' => $lang->var,      'required' => true);
        self::$settings['varGroup'] = array('name' => 'varGroup', 'label' => $lang->var,      'required' => true);
        self::$settings['sub']      = array('name' => 'sub',      'label' => $lang->sub);
        self::$settings['groupNum'] = array('name' => 'groupNum', 'label' => $lang->groupNum, 'required' => true);
        self::$settings['groupCol'] = array('name' => 'groupCol', 'label' => $lang->groupNum, 'required' => true);
        self::$settings['multiple'] = array('name' => 'multiple', 'label' => $lang->multiple);
        self::$settings['sd']       = array('name' => 'sd',       'label' => $lang->sd);
        self::$settings['mean']     = array('name' => 'mean',     'label' => $lang->mean);
        self::$settings['xRef']     = array('name' => 'xRef',     'label' => $lang->xRef);
        self::$settings['sRef']     = array('name' => 'sRef',     'label' => $lang->sRef);
        self::$settings['tests']    = array('name' => 'tests',    'label' => $dasLang->spc->tests);

        /* Type settings */
        self::$settings['group']    += array('type' => 'enum', 'enumOptions' => $lang->groupEnum, 'columnType' => 'any', 'defaultValue' => 'false');
        self::$settings['var']      += array('type' => 'list', 'listType' => 'column', 'columnType' => 'number');
        self::$settings['varGroup'] += array('type' => 'list', 'listType' => 'column', 'columnType' => 'number');
        self::$settings['sub']      += array('type' => 'enum', 'enumOptions' => $lang->subEnum, 'defaultValue' => 'number');
        self::$settings['groupNum'] += array('type' => 'number');
        self::$settings['groupCol'] += array('type' => 'column');
        self::$settings['multiple'] += array('type' => 'list', 'listType' => 'number');
        self::$settings['sd']       += array('type' => 'number');
        self::$settings['mean']     += array('type' => 'number');
        self::$settings['xRef']     += array('type' => 'list', 'listType' => 'number');
        self::$settings['sRef']     += array('type' => 'list', 'listType' => 'number');
        self::$settings['tests']    += array('type' => 'list', 'listType' => 'enum', 'enumOptions' => $dasLang->spc->testsRules, 'ui' => 'checkbox-list', 'defaultValue' => array('1'));

        /* limit settings */
        self::$settings['var']      += array('conditions' => array('group' => 'true'), 'listLength' => 2);
        self::$settings['varGroup'] += array('conditions' => array('group' => 'false'));
        self::$settings['sub']      += array('conditions' => array('group' => 'false'));
        self::$settings['groupNum'] += array('conditions' => array('group' => 'false', 'sub' => 'number'), 'pattern' => "/^[1-9]\d*$/", 'error' => $dasLang->XbarS->errorGroup, 'min' => 1, 'max' => 101);
        self::$settings['groupCol'] += array('conditions' => array('group' => 'false', 'sub' => 'column'));

        self::$settings['multiple'] += array('pattern' => "/^[\d]+(\.[\d]+)?$/",                'error' => $lang->errorMultiple);
        self::$settings['sd']       += array('pattern' => "/^([1-9]\d*)(\.[\d]+)?$|^0\.\d+?$/", 'error' => $lang->errorSD);
        self::$settings['mean']     += array('pattern' => "/^[\+\-]?[\d]+(\.[\d]+)?$/",         'error' => $lang->errorMean);
        self::$settings['xRef']     += array('pattern' => "/^[\d]+(\.[\d]+)?$/",                'error' => $lang->errorXRef);
        self::$settings['sRef']     += array('pattern' => "/^[\d]+(\.[\d]+)?$/",                'error' => $lang->errorSRef);

        /* col grid settings */
        self::$settings['group']    += array('col' => 6);
        self::$settings['sub']      += array('col' => 6);

        /* more settings */
        self::$settings['multiple'] += array('paramType' => 'more');
        self::$settings['sd']       += array('paramType' => 'more');
        self::$settings['mean']     += array('paramType' => 'more');
        self::$settings['xRef']     += array('paramType' => 'more');
        self::$settings['sRef']     += array('paramType' => 'more');
        self::$settings['tests']    += array('paramType' => 'more');

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

        return self::$settings;
    }

    /**
     * Get config.
     *
     * @access public
     * @return object
     */
    public static function getConfig()
    {
        global $dasLang;
        $lang = $dasLang->config;
        self::$config['grid']   = $lang->gridConfig;
        self::$config['legend'] = $lang->legendConfig;

        return self::$config;
    }

    /**
     * Get Setting column type.
     *
     * @param string $index
     * @access public
     * @return string
     */
    public static function columnType($index)
    {
        return self::$settings[$index]['columnType'];
    }

}
