<?php
use PHPUnit\Framework\TestCase;
use app\p\service\MenuNutritionCalculator;
class IndependentAlgorithmTest extends TestCase
{
 private function dish($id) {return ['id'=>$id,'uuid'=>'d'.$id,'name'=>'菜'.$id,'category_one'=>6,'weight'=>100,'fat'=>3,'protein'=>24,'dietary_fiber'=>6,'purine'=>50,'gl'=>5,'cook_method'=>1,'tags'=>[]];}
 public function testRankingsAgainstIndependentFixedSeedOracle() {
  mt_srand(1392);$d=[];$expected=[];$union=[];
  $rules=['fat'=>['fat:3',1],'protein'=>['protein:1',-1],'dietary_fiber'=>['dietary_fiber:1',-1],'purine'=>['purine:3',1]];
  for($id=1;$id<=100;$id++) {
   $row=$this->dish($id);$row['weight']=mt_rand(1,4)*50;
   foreach($rules as $field=>$rule){$row[$field]=mt_rand(0,20)*$row['weight']/100;if(mt_rand(0,1)){$row['tags'][]=$rule[0];$expected[$field][]=['id'=>$id,'value'=>$row[$field]/$row['weight']*100];$union[$id]=true;}}
   $d[]=$row;
  }
  $r=(new MenuNutritionCalculator)->single(array_merge($d,array_slice($d,0,20)),[]);
  $this->assertSame(100,$r['dish_count']);$this->assertSame(count($union),$r['nutrition_count']);
  foreach($rules as $field=>$rule) {
   usort($expected[$field],function($a,$b)use($rule){return (($a['value']<=>$b['value'])*$rule[1]) ?: ($a['id']<=>$b['id']);});
   $this->assertSame(array_map(function($x){return 'd'.$x['id'];},$expected[$field]),array_column($r['rankings'][$field]['list'],'dish_id'));
   $this->assertEquals(count($expected[$field]),$r['rankings'][$field]['ratio']);
  }
 }
 public function testRawCookingThresholdBeforeRoundedPercentage() {
  $d=[];for($i=1;$i<=9999;$i++){$x=$this->dish($i);$x['cook_method']=$i<=8999?1:2;$d[]=$x;}
  $r=(new MenuNutritionCalculator)->single($d,[1=>['enum_name'=>'推荐其他','recommend'=>1],2=>['enum_name'=>'非推荐其他','recommend'=>2]]);
  $this->assertSame(90.0,$r['cooking']['ratio']);$this->assertFalse($r['cooking']['reasonable']);
 }
 public function testIngredientQualificationAroundFiftyAndTen() {
  $c=new MenuNutritionCalculator;
  foreach([[49.999,10,0],[50,9.999,1],[50,10,2]] as $v) {
   $rows=[['dishes_uuid'=>'d1','composition_name'=>'菠菜','composition_ratio'=>$v[0],'category'=>6,'minute_sort'=>38],['dishes_uuid'=>'d1','composition_name'=>'白菜','composition_ratio'=>$v[1],'category'=>6,'minute_sort'=>39]];
   // 49.999+10已达到50，故第一个样本用另一类补足配方，不计目标分类。
   if($v[0]<50)$rows[1]['category']=3;
   $r=$c->structures([$this->dish(1)],$rows,[]);$this->assertSame($v[2],$r['vegetable']['count']);
  }
 }
 public function testFatClassificationBoundariesUsePer100Grams() {
  $c=new MenuNutritionCalculator;
  foreach([[10,'畜禽瘦肉'],[10.01,'肥瘦相间'],[29.99,'肥瘦相间'],[30,'肥肉']] as $v){
   $d=$this->dish(1);$d['weight']=200;$d['fat']=$v[0]*2;
   $r=$c->structures([$d],[['dishes_uuid'=>'d1','composition_name'=>'肉','composition_ratio'=>100,'category'=>3,'minute_sort'=>0]],[]);
   $counts=array_column($r['meat']['list'],'count','name');$this->assertSame(1,$counts[$v[1]]);
  }
 }
 public function testAllVitaminTagsAndMultipleTagsHaveSingleCategoryLabel() {
  $c=new MenuNutritionCalculator;
  foreach(['va','vb1','vb2','vc','ve'] as $tag){$d=$this->dish(1);$d['category_one']=15;$d['tags']=[$tag.':1'];$this->assertSame(['label'=>'高维生素','matched'=>true],$c->nutrition($d));}
  $d['tags']=['va:1','vc:1','ve:1'];$this->assertSame(['label'=>'高维生素','matched'=>true],$c->nutrition($d));
  $d['category_one']=6;$this->assertFalse($c->nutrition($d)['matched']);
 }
}
