<?php

namespace app\controller;

use support\Request;
use support\Db;
use support\Apriori;
use \CodedHeartInside\DataMining\Apriori\Installer; 
//https://github.com/codedheartinside/php-apriori

class CbaController
{
    public function smt_cba_1(Request $request)
    {
        set_time_limit(3600 * 10);
        $zcd = 0.01;
		$data = [];
        Db::table('smt_cba_1')->truncate();
        $orderCount = Db::table('smt_cba_base')->count();
        Db::table('smt_cba_base')->select('scb_p_id')->orderBy('scb_p_id')->distinct()
        ->chunkById(1000, function ($rows)use($orderCount,$zcd) {
            $insertData = [];
            foreach ($rows as $row) {
                $itemCount = Db::table('smt_cba_base')->where(['scb_p_id'=>$row->scb_p_id])->count();
                $zcdValue = round($itemCount/$orderCount*100,4);
                if($zcdValue>=$zcd){
                    $insertData[] = ['scba1_p_id' => $row->scb_p_id, 'scba1_zcd' => $zcdValue ];
                }
            }
            if(!empty($insertData)) Db::table('smt_cba_1')->insert($insertData);
        },'scb_p_id');
        $data['orderCount'] = $orderCount;
		return response(put($data));
    }

    public function smt_cba_2(Request $request)
    {
        set_time_limit(3600 * 10);
        ini_set('memory_limit', '4096M');
        $pidArr = [];
        $rows = Db::table('smt_cba_1')
                ->get();
        foreach($rows as $row){
            $pidArr[] = $row->scba1_p_id;
        }
        $pidCount = count($pidArr);
        $rows = Db::table('smt_cba_base')
                ->join('smt_cba_1', 'smt_cba_base.scb_p_id', '=', 'smt_cba_1.scba1_p_id')
                ->select('scb_custnumber','scb_p_id')->orderBy('scb_custnumber')
                ->get();
        $keyValues = [];
        foreach($rows as $row){
            $keyValues[$row->scb_custnumber][] = $row->scb_p_id;
        }
        unset($rows);
        $dataset = [];
        for($i=0;$i<$pidCount;$i++){
            $item1 = $pidArr[$i];
            for($j=0;$j<$pidCount;$j++){
                if($i!=$j){
                    $item2 = $pidArr[$j];
                    foreach($keyValues as $custnumber=>$values){
                        if(in_array($item1,$values) && in_array($item2,$values)){
                            $itemBoth = $item1.','.$item2;
                            if(!isset($dataset[$itemBoth])) $dataset[$itemBoth] = 0;
                            $dataset[$itemBoth]++;
                        }
                    }
                }
            }
        }
        unset($keyValues);
        Db::table('smt_cba_2')->truncate();
        //Db::query("ALTER TABLE smt_cba_2 DROP INDEX scba2_pid1");
        $insertData = [];
        foreach($dataset as $itemBoth=>$count){
            if($count<5){
                unset($dataset[$itemBoth]);
            }else{
                $sup = $count;
                $tmpArr = explode(',',$itemBoth);
                foreach($tmpArr as $k=>$v){ $tmpArr[$k] = $v*1; }
                $pids = json_encode($tmpArr);
                $insertData[] = ['scba2_pid1'=>$tmpArr[0],'scba2_pid2'=>$tmpArr[1],'scba2_pids'=>$pids,'scba2_sup'=>$sup];
                if(count($insertData)>=1000){
                    Db::table('smt_cba_2')->insert($insertData);
                    $insertData=[];
                }
            }
        }
        if(!empty($insertData)) Db::table('smt_cba_2')->insert($insertData);
        //Db::query("ALTER TABLE smt_cba_2 ADD INDEX (scba2_pid1)");
		return response(put(['ok']));
    }

    public function smt_apriori(Request $request){
        set_time_limit(3600 * 10);
        ini_set('memory_limit', '10240M');
        $rows = Db::table('smt_cba_base')
                ->join('smt_cba_1', 'smt_cba_base.scb_p_id', '=', 'smt_cba_1.scba1_p_id')
                ->select('scb_custnumber','scb_p_id')->orderBy('scb_custnumber')
                ->where('scba1_zcd','>',0.03)
                ->get();
        $keyValues = [];
        foreach($rows as $row){
            $keyValues[$row->scb_custnumber][] = $row->scb_p_id;
        }
        $dataset = [];
        foreach($keyValues as $values){
            $dataset[] = implode(',',$values);
        }
        unset($keyValues);
		//return response(put($dataset));
        $Apriori = new Apriori();
        $Apriori->setMaxScan(20);       //Scan 2, 3, ...
        $Apriori->setMinSup(5);         //Minimum support 1, 2, 3, ...
        $Apriori->setMinConf(75);       //Minimum confidence - Percent 1, 2, ..., 100
        $Apriori->setDelimiter(',');    //Delimiter 
        /*
        $dataset   = array();
        $dataset[] = 'A,B,C,D' ;
        $dataset[] = 'A,D,C';
        $dataset[] = 'B,C';
        $dataset[] = 'A,E,C';
        
        print_r($dataset);*/
        $Apriori->process($dataset);

        //Frequent Itemsets
        
        $data = $Apriori->getFreqItemsets();
        unset($dataset);
        Db::table('smt_cba_2')->truncate();
        foreach($data as $k=>$v){
            $sup = $v['sup'];
            $tmpArr = [];
            foreach($v as $ak=>$a){
                if(is_int($ak)) $tmpArr[] = $a*1;
            }    
            $pids = json_encode($tmpArr);
            $insertData = ['scba2_pids'=>$pids,'scba2_sup'=>$sup];
            Db::table('smt_cba_2')->insert($insertData);
        }
		return response(put(['ok']));
        
    }

    public function smt_apriori2(Request $request)
    {
        set_time_limit(3600 * 10);
        ini_set('memory_limit', '4096M');
        $rows = Db::table('smt_cba_base')
                ->join('smt_cba_1', 'smt_cba_base.scb_p_id', '=', 'smt_cba_1.scba1_p_id')
                ->select('scb_custnumber','scb_p_id')->orderBy('scb_custnumber')
                ->where('scba1_zcd','>',0.03)
                ->get();
        $keyValues = [];
        foreach($rows as $row){
            $keyValues[$row->scb_custnumber][] = $row->scb_p_id;
        }
        $dataset = [];
        foreach($keyValues as $values){
            if(count($values)>1){
                $dataset[] = $values;
            }
        }
        unset($keyValues);
        //$installer = new Installer();
        //$installer->createRunningEnvironment();
        $aprioriConfiguration = new \CodedHeartInside\DataMining\Apriori\Configuration();

        // Configuring the boundries is optional
        $aprioriConfiguration->setDisplayDebugInformation();
        $aprioriConfiguration->setMinimumThreshold(2) // Default is 2
            ->setMinimumSupport(0.02) // Default is 0.1
            ->setMinimumConfidence(5) // Default is 0.2
        ;
        /*
        $dataset = array(
            array(1, 3, 4),
            array(2, 4, 6),
            array(1, 2),
            array(5),
        );*/
        
        $dataInput = new \CodedHeartInside\DataMining\Apriori\Data\Input($aprioriConfiguration);
        $dataInput->flushDataSet()
            ->addDataSet($dataset)
            //->addDataSet($dataset) // In this case, the data set is added twice to create more testing data
        ;
 
        $aprioriClass = new \CodedHeartInside\DataMining\Apriori\Apriori($aprioriConfiguration);
        $aprioriClass->run();
        Db::table('smt_cba_2')->truncate();
        /*
        foreach ($aprioriClass->getSupportRecords() as $record) {
            if( count($record['itemIds']) > 1){
                $sup = $record['support'];
               
                $pids = json_encode($record['itemIds']);
                $insertData = ['scba2_pids'=>$pids,'scba2_sup'=>$sup];
                Db::table('smt_cba_2')->insert($insertData);
            }
        }*/
        foreach ($aprioriClass->getConfidenceRecords() as $record) {
            if( count($record['if']) > 1){
                $sup = $record['then'];
               
                $pids = json_encode($record['if']);
                $insertData = ['scba2_pids'=>$pids,'scba2_sup'=>$sup];
                Db::table('smt_cba_2')->insert($insertData);
            }
        }        
		return response(put(['ok']));
    }

}