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

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

    /* 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();

        $multiple = U::formatMultiple($settings['multiple']);
        $ref      = U::formatReference($settings['ref']);

        $type     = 'number';
        $vars     = $settings['var'];
        $sub      = $settings['sub'];
        $groupNum = $settings['groupNum'];
        $groupCol = $settings['groupCol'];
        $tests    = isset($settings['tests']) ? $settings['tests'] : '';

        $sliceDF = $dataframe->sliceDataframe($dataframe, $vars, $type);

        $check = new checkData();
        $check->setDataList($sliceDF->colsData($vars), $sliceDF->colsName($vars), self::$settings['var']['validate']);

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

        $u = new U($sliceDF);
        if($sub == 'column')
        {
            $check = new checkData();
            $check->setData($dataframe->colData($groupCol), $dataframe->columns[$groupCol], self::$settings['groupCol']['validate']);
            $check->setDataList($dataframe->colsData($vars), $dataframe->colsName($vars), self::$settings['var']['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);
        }
        foreach($vars as $var)
        {
            if($sub == 'number')
            {
                $points = $sliceDF->col($var)->data;
                foreach($points as $key => $point)
                {
                    if($points[$key] != null) $points[$key] = $point/$groupNum;
                }

                $μ = $u->uBar($var, $groupNum, $type);
                $σ = $u->sigma($var, $groupNum, $type);

                $limit = $u->limit($μ, $σ, $multiple, 3, $points);

                /* Std ULCLs */
                $stdLimit = $u->limit($μ, $σ, array(1,2,3));
                $stdULCLs = $stdLimit->SLs;
                $stdULCLs['C'] = $stdLimit->CL;
            }
            else
            {
                $points       = $sliceDF->col($var)->data;
                $groupData    = $sliceDF->col($groupCol)->data;
                $beforePoints = array();
                list($points, $groupData, $beforePoints) = $u->setNull($points, $groupData);
                $μ = $u->uGroupBar($beforePoints, $groupData);
                $σ = $u->groupSigma($beforePoints, $groupData);

                $limit = $u->limit($μ, $σ, $multiple, 3, $points);

                /* Std ULCLs */
                $stdLimit = $u->limit($μ, $σ, array(1,2,3), 3, $points);
                $stdULCLs = $stdLimit->SLs;
                $stdULCLs['C'] = $stdLimit->CL;
            }
            $title = $dataframe->getChartTitle($var, $lang->perfanalysis->methods->control['U']);

            /* Std ULCLs */

            $param = new stdclass();

            $param->lang         = $dasLang->U;
            $param->points       = $points;
            $param->name         = $dataframe->columns[$var];
            $param->lineBegin    = 0;
            $param->lineEnd      = count($param->points) - 1;
            $param->CL           = $μ;
            $param->CLName       = $dasLang->U->cl;
            $param->ULCLs        = $limit->SLs;
            $param->title        = $title;
            $param->xTitle       = $dasLang->U->sample;
            $param->yTitle       = $dasLang->U->samplePerUnit;
            $param->testsResults = SPC::checkTestsRules($points, $stdULCLs, $tests);
            $param->ref          = $ref;

            $textResult = $dataframe->getTextResult($dataframe->getChartTitle($var, $lang->perfanalysis->methods->control['U']));
            $textResult->name     = 'var' . $var;
            $textResult->children = 1;

            $result[] = $textResult;
            $result[] = SPC::buildChartResult($param);

            if(!empty($param->testsResults))
            {
                $result[] = SPC::buildTestsResult($param->testsResults, $dasLang->U->samplePerUnit, array($var));
            }
        }

        return $result;
    }

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

        /* Basic settings */
        self::$settings['var']      = array('name' => 'var',      'label' => $lang->var,      'required' => true);
        self::$settings['multiple'] = array('name' => 'multiple', 'label' => $lang->multiple);
        self::$settings['ref']      = array('name' => 'ref',      'label' => $lang->ref);
        self::$settings['sub']      = array('name' => 'sub',      'label' => $lang->groupData);
        self::$settings['groupNum'] = array('name' => 'groupNum', 'label' => $lang->groupNum, 'required' => true);
        self::$settings['groupCol'] = array('name' => 'groupCol', 'label' => $lang->groupCol, 'required' => true);
        self::$settings['tests']    = array('name' => 'tests',    'label' => $dasLang->cu->tests);

        /* Type settings */
        self::$settings['var']      += array('type' => 'list', 'listType' => 'column', 'columnType' => 'number');
        self::$settings['multiple'] += array('type' => 'list', 'listType' => 'number');
        self::$settings['ref']      += array('type' => 'list', 'listType' => 'number');
        self::$settings['sub']      += array('type' => 'enum', 'enumOptions' => $lang->subEnum, 'columnType' => 'any', 'defaultValue' => 'number');
        self::$settings['groupNum'] += array('type' => 'number');
        self::$settings['groupCol'] += array('type' => 'column', 'listType' => 'column', 'columnType' => 'number');
        self::$settings['tests']    += array('type' => 'list', 'listType' => 'enum', 'enumOptions' => $dasLang->cu->testsRules, 'ui' => 'checkbox-list', 'defaultValue' => array('1'));

        /* Limit settings */
        self::$settings['multiple'] += array('pattern' => "/^[\d]+(\.[\d]+)?$/", 'error' => $lang->errorMultiple);
        self::$settings['ref']      += array('pattern' => "/^[\d]+(\.[\d]+)?$/", 'error' => $lang->errorRef);
        self::$settings['groupNum'] += array('conditions' => array('sub' => 'number'), 'pattern' => "/^([1-9]\d*)(\.[\d]+)?$|^0\.\d+?$/", 'error' => $lang->errorGroup);
        self::$settings['groupCol'] += array('conditions' => array('sub' => 'column'));

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

        /* More settings */
        self::$settings['multiple'] += array('paramType' => 'more');
        self::$settings['ref']      += array('paramType' => 'more');
        self::$settings['tests']    += array('paramType' => 'more');

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

        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;
    }
}
