[PHP] Pagina conta verghe per carpenteria

Felotti

Nuovo Utente
7 Ott 2019
14
0
1
Buongiorno a tutti.
Sto creando, tramite php, una sorta di "programma conta verghe (tubi)".
Mi spiego meglio.
In molte carpenterie sono presenti delle macchine laser che tagliano le verghe (ossia i tubi) in vari pezzi disegnati dagli uffici tecnici.
Queste verghe hanno una lunghezza fissa di 5800 mm.
Ora, mettiamo il caso che in ordine ci sono:
5 pezzi di lunghezza 3000 mm
5 pezzi di lunghezza 2000 mm
5 pezzi di lunghezza 500 mm
e 5 pezzi di lunghezza 300 mm
Per ottimizzare la quantità di verghe da utilizzare, bisogna far si che in ogni verga ci sia il maggior numero di pezzi possibili.
Per esempio:
Verga 1: 1 pezzo da 3000 mm, 1 pezzo da 2000 mm, 1 pezzo da 500 mm e un pezzo da 300mm.
Si procede così fino a quanto le quantità da produrre vengono termitate.
Al giorno d'oggi questa gestione avviene manualmente, ma con l'avvento delle nuove tecnologie bisogna ottimizzarsi sotto ogni punto di vista.
Ora, io mi sto cimentando in questa programmazione ma mi sorgono delle difficoltà (non utilizzando php e html da diverso tempo).
Avevo in mente di chiedere all'utente il numero di articoli da dover tagliare (nell'esempio precedente 4 per intenderci), in modo da generare un array multidimensionale composto da 4 righe.
Tramite il metodo POST (o anche GET dato che non sono dati sensibili), ricevere questa informazione dalla pagina html e generare questo array dove si richiedono anche:
Dimensioni dei pezzi, quantità e codice articolo.
Avendo un risultato del genere:
$fabbisogni = array(
"Codice" => array ();
"Dimensione" => array ();
"Quantità" => array ();
);
Dopodichè, tramite cicli for e while, ottimizzare l'utilizzo delle verghe e stampare a video il numero di verghe utilizzate ed il modo in cui vengono utilizzate, per ottenere un risultato simile:

Numero verghe utilizzate: 5
Verga 1: codice1 (3000 mm quantità 1), codice2 (2000mm quantità 1) ...... e così via.
Verga 2: .....
.....

N.B: Se in una verga avanzano, per esempio, 200 mm, ma il pezzo più piccolo misura 300 mm, non posso utilizzare questi 200 mm e 100 mm di un'altra verga. La quantità rimasta sarebbe dunque da considerare "scarto".

Mi sorgono delle difficoltà nella creazione dinamica di questi array e nei cicli.
Qualcuno può darmi una mano? :(

Grazie in anticipo
 
Ultima modifica:

macus_adi

Utente Attivo
5 Dic 2017
1.209
77
48
IT/SW
Prova con questa, non è ottimizzata ma ti da una base:
PHP:
<?php
/**
* Created by phpS
* User: macus_adi
* Project Name: _CI_utilsLibs
* File: Goptimeze.php
* Path: Goptimeze
* Date: 09/10/2019
* Time: 10:49
*/

class Goptimeze {

   public $mLen=5800;

   public $result=[];

   public $html='';

   public function __construct() {
      ini_set('memory_limit',-1);
   }
   public function creaLen($data){
      $bs=[];
      foreach ($data as $k=>$v){
         (!isset($bs[$v[1]]))?$bs[$v[1]]=$v[0]:$bs[$v[1]]+=$v[0];
      }
      krsort($bs);
      $data=[];
      foreach ($bs as $k=>$v){
         $data[]=[$v,$k];
      }
      foreach ($data as $items){
         $this->creaTravi($items);
      }
      $this->createOutput();
      return $this;
   }
   public function creaTravi($data){
      for($i=0;$i<$data[0];$i++){
         if($this->findInPath($data))$this->findLocation($data[1]);
      }
   }
   public function findInPath($data){
      $num=$data[0];
      $el=0;
      foreach ($this->result as $k=>$v){
         foreach ($v['values'] as $items){
            if($items==$data[1])$el++;
         }
      }
      if($el>=$num)return false;
      else return true;
   }
   public function findLocation($len){
      if(empty($this->result))$this->Trave($len);
      else{
         $loc=false;
         foreach ($this->result as $k=>$v){
            if(!$loc && $this->result[$k]['len']-$len>=0){
               $this->result[$k]['values'][]=$len;
               $this->result[$k]['len']-=$len;
               $loc=true;
            }
         }
         if(!$loc)$this->Trave($len);
      }
   }
   public function Trave($in){
      $this->result[]=['values'=>[$in],'len'=>$this->mLen-$in];
   }

   public function createOutput(){
      $table='<table>
      <thead><tr><th>Taglio</th><th>Elementi</th><th>Sfreddo</th></tr></thead><tbody></tbody>';
      foreach ($this->result as $k=>$v){
         $table.='<tr><td>'.($k+1).'</td><td><ul>';
         foreach ($v['values'] as $items)$table.='<li>'.$items.'</li>';
         $table.='</ul></td><td>'.$v['len'].'</td></tr>';
      }
      $table.='</tbody></table>';
      return $this->html=$table;
   }

}
Per richiamarla basta fare in questo modo, non so se funziona come credi o se ha qualche bug...

PHP:
$opt=new Goptimeze();
$data=[
   [5,2000],
   [5,500],
   [5,300],
   [3,250],
   [15,575],
   [10,25],
   [4,1300],
   [5,3000],
];
echo $opt->creaLen($data)->html;
Ho aggiunto qualche dato per elaborare il tutto e per vedere in che modo si comporta....

Naturalmente manca, la gestione delle possibili varianti per limitare gli sfreddi (residuo) di ogni trave, ottimizzazione e calcolo del taglio
 
  • Like
Reactions: Felotti

Felotti

Nuovo Utente
7 Ott 2019
14
0
1
Ciao Macus_adi
Innanzitutto ti ringrazio molto per il tempo che mi hai dedicato.
Appena rientro in ufficio testo il tutto.
Sto ultimando il file html per la richiesta all'utente dei fabbisogni in modo da farlo interagire con il codice PHP che mi hai mandato.
Ti do aggiornamenti il prima possibile
 

macus_adi

Utente Attivo
5 Dic 2017
1.209
77
48
IT/SW
Modifica il metodo createOutput in questo modo!:
PHP:
public function createOutput(){
   $table='<table>
   <thead><tr><th>Taglio</th><th>Elementi</th><th>Numero Tagli</th><th>Sfreddo</th></tr></thead><tbody></tbody>';
   $all_t=0;
   $sf=0;
   foreach ($this->result as $k=>$v){
      $table.='<tr><td>'.($k+1).'</td><td><ul>';
      $all_t+=count($v['values']);
      foreach ($v['values'] as $items)$table.='<li>'.$items.'</li>';
      $table.='</ul></td><td>'.count($v['values']).'</td><td>'.$v['len'].'</td></tr>';
      $sf+=$v['len'];
   }
   $table.='</tbody>';
   $table.='<tfoot><tr><th>Barre: '.count($this->result).'</th>
   <th></th><th>Tagli : '.$all_t.'</th><th>Sfreddo : '.$sf.'</th></tr></tfoot>';
   $table.='</table>';
   return $this->html=$table;
}
 

Allegati

Felotti

Nuovo Utente
7 Ott 2019
14
0
1
Ho provato a scrivere un codice alternativo (senza iterazione con il client) per "semplificare" il codice.
Te lo allego di seguito, fammi sapere che ne pensi
PHP:
    $lunghezze_pezzi = array ("3000", "2000", "500", "800"); //array lunghezze pezzi
    $quantita = array ("5", "5", "5", "5"); //array quantità
    $tubo_corrente = array (); //memorizzo in che modo vengono tagliato il tubo
    $risultato = array(); //array composto dai vari array dei tubi tagliati
    $sfridi = array (); //verifico gli sfridi di verga in verga
    $tubo = 5800; //lunghezza iniziale tubo
    $verghe_tagl = 0; //numero di verghe utilizzate

    for($i=0; $i<count($lunghezze_pezzi); $i++){  //scorrimento array lunghezze
        for($j=0; $j<count($quantita); $j++){  //scorrimento array quantità
            if($i!=0){ $n=$lunghezze_pezzi[$i-1]; //variabile per verifica valore maggiore
            }else $n=0; //se sono al primo ciclo la variabile per la verifica del valore maggiore rimane a 0
            if($lunghezze_pezzi[$i] > $n && $quantita[$j] != 0){  //verifico che il pezzo abbia una lunghezza maggiore del precedente e che la sua quantità non sia 0
                $n=$lunghezze_pezzi[$i]; //aggiungo la dimensione più lunga dei tubi da tagliare alla variabile di inserimento
            }
            if($tubo > $n){  //controllo che il tubo abbia la dimensione necessaria al taglio di quel pezzo
                $tubo=$tubo-$n; //taglio il tubo togliendo la quantità tagliata
                $quantita[$j]=$quantita[$j]-1; //diminuisco di 1 la quantità del tubo tagliato
                array_push($tubo_corrente, $n); //inserisco nell'array dei pezzi tagliati in ogni verga la dimensione del pezzo appena tagliato
            }else{
                for($k=0; $k<count($lunghezze_pezzi); $k++){ //verifico se ci sono altri pezzi da poter tagliare nel tubo
                    if($tubo > $lunghezze_pezzi[$k] && $quantita[$k] != 0) $temp=1; //se ce ne sono metto la variabile di controllo a 1
                    else{
                        $temp=0; //se non ce ne sono la variabile andrà a 0
                        $verghe_tagl += 1; //dato che il tubo è stato completamente tagliato, aumento la quantità delle verghe utilizzate di 1
                        array_push($sfridi, $tubo);  //memorizzo lo sfrido della verga appena tagliata
                        $tubo = 5800; //riporto la variabile tubo alla lunghezza max dato che cambierò tubo
                    }
                }
                if($temp=0){ //verifico che non ci siano più pezzi che ci possano stare nello sfrido
                    array_push($risultato, $tubo_corrente); //inserisco l'array dei pezzi tagliati nel tubo all'interno dell'array che conterrà tutti i tubi tagliati
                    $tubo_corrente=array(); //riporto l'array del tubo corrente a 0 in modo che si possa iniziare un altro tubo da capo
                }
            }
        }
    }
    for($z=0; $z<count($lunghezze_pezzi); $z++){ //controllo se ci sono ancora dei pezzi da tagliare
        if($quantita[$z] !=0) $x=1; //se ne restano altri metto la variabile x a 1
    }
    if($x=0){
        echo $risultato; //stampo come vengono tagliati i tubi
        echo $verghe_tagl; //stampo il numero di verghe utilizzate
    }
 

macus_adi

Utente Attivo
5 Dic 2017
1.209
77
48
IT/SW
for($z=0; $z<count($lunghezze_pezzi); $z++){ //controllo se ci sono ancora dei pezzi da tagliare
if($quantita[$z] !=0) $x=1; //se ne restano altri metto la variabile x a 1
}
E se invece non ne resta nessuno?
X è indefinita....
echo $risultato;
Non puoi fare echo su oggetti/array....
In definitiva provata e non funzionante...
Non ho idea di cosa volessi fare con tutti quei cicli....
Non mi piace.... Se rispecchia le tue esigenze OK!
Altra nota, così come hai impostato il tutto cambiando l'ordinamento degli elementi hai questa situazione:
PHP:
$lunghezze_pezzi = array ("3000",  "500", "800","2000"); //array lunghezze pezzi
$quantita = array ("5", "5", "5", "5"); //array quantità
3000 500 500 500 500 500 = 300
3000 800 800 800 800 = 400
2000 2000 800 = 1000
2000 2000 = 1800
2000 = 3800
etc.....

Rispetto all'ottimizzazione
3000 2000 800= 0
3000 2000 800= 0
3000 2000 800= 0
3000 2000 800= 0
3000 2000 800= 0
500 500 500 500 500= 3300


Non hai gestito l'ordinamento e la gestione delle posizioni per completare i tagli!

Per fare la prova con ordinamento e senza ordinamento prova a modificare la classe che ti ho mandato commentando questa dalla linea 25 alla 32:
PHP:
/*foreach ($data as $k=>$v){
   (!isset($bs[$v[1]]))?$bs[$v[1]]=$v[0]:$bs[$v[1]]+=$v[0];
}
krsort($bs);
$data=[];
foreach ($bs as $k=>$v){
   $data[]=[$v,$k];
}*/
 
Ultima modifica:

Felotti

Nuovo Utente
7 Ott 2019
14
0
1
Hai ragione, ho sbagliato tutto praticamente :D
Una sola domanda
Come potrei memorizzare all'interno della matrice $data dei valori ricevuti con $_POST? (Ovviamente senza sapere quanti dati potrebbe inserire l'utente
 

Felotti

Nuovo Utente
7 Ott 2019
14
0
1
Stavo utilizzando il tuo codice con i valori in $data inseriti manualmente e funziona correttamente in base alle mie esigenze.
Ora sto provando a completare l'array con valori ricevuti da 'POST', organizzandomi in questo modo:

PHP:
$quantita = $_POST['quantita'];
$lunghezza = $_POST['lunghezza'];

$data = [ /*quantita*/, /*lunghezze*/ ]
Solo che non riesco a far si che in $data ci vadano quantità e lunghezze come hai creato te la matrice manualmente.

Mettiamo il caso che io riceva i seguenti valori da HTML:

PHP:
$quantita = (5, 10, 10, 10, 5, 20, 25)
$lunghezze = (1000, 1200, 2500, 1500, 500, 300, 3000)
Ora, come posso far si che la matrice si compili come segue?

PHP:
$data = [
[5, 1000],
[10, 1200],
[10, 2500],
[10, 1500],
[5, 500],
[20, 300],
[25, 3000]];
In modo tale da non effettuare alcuna modifica al codice che mi hai fornito
 

Felotti

Nuovo Utente
7 Ott 2019
14
0
1
Ho creato 3 file
In uno chiedo il numero di codici differenti da dover tagliare, in modo che nel secondo file io possa far si che all'utente appaiano n richieste di lunghezze e quantità, che a loro volta verranno inviate al file con il quale calcolo il tutto.
Purtroppo però non funziona e non ne capisco il motivo o_O
Allego i 3 file
 

Allegati

macus_adi

Utente Attivo
5 Dic 2017
1.209
77
48
IT/SW
Hai fatto un macello nei file.....
Controller richiama la view
PHP:
public function createForm(){
   if(empty($this->input->post())){
      $this->load->view('createForm');
   }else{
      $this->load->view('createLen',['data'=>$this->input->post('np')]);
   }
}
public function parseRequest(){
   $data=[];
   foreach ($this->input->post('data')as $k=>$v){
      $data[]=[$v['qta'],$v['len']];
   }
   $opt=new Goptimeze();
   echo $opt->creaLen($data)->html;
   print_r($opt->result);
}
View createForm
Codice:
<form method="post">
   <input type="number" name="np" min="0" max="20" class="form-control" required>
   <br>
   <button type="submit">invia</button>
</form>
View createLen
Codice:
<form action="/CONTROLLER/parseRequest" method="post">
<table>
   <thead>
   <tr>
      <th></th>
      <th>Lunghezza</th>
      <th>Qauntità</th>
   </tr>
   </thead>
   <tbody>
   <?php
   for($i=0;$i<$data;$i++){
      echo '<tr><td>'.($i+1).'</td>
         <td><input type="number" min="0" required max="5800" name="data['.$i.'][len]"></td>
         <td>
         <input type="number" min="0" required max="5800" name="data['.$i.'][qta]"></td>
         </td>';

   }
   ?>
   </tbody>
   <tfoot>
   <tr>
      <th colspan="3">
         <button type="submit">Salva</button>
      </th>
   </tr>
   </tfoot>
</table>
</form>
 
  • Like
Reactions: Felotti

Felotti

Nuovo Utente
7 Ott 2019
14
0
1
Perfetto, io ora ho questi 3 file che trovi nell'allegato.

CreateForm.php
ParseRequest.php
risultato.php

I primi due funzionano correttamente
Il problema lo riscontro nell'ottenere il risultato finale in quanto non mi ritorna nulla.
Riesci a darmi questo ultimo aiuto?
Mi salveresti la vita:rolleyes:

Scusa la mia ignoranza e ti ringazio tantissimo per il tempo che mi stai dedicando, ma credo che mi sto creando dei complessi che non mi portano a nulla
 

Allegati

Ultima modifica: