I'm doing a practice project for my Java programming class and I found a problem that I can't see.
The program simulates a pizzeria. You can choose the size, type of dough, ingredients, etc... of the pizza and the program recalculates the price as options are changed. When the time comes, if you click on "Add to order", the application saves the pizza in a list of pizzas and shows you the summary of the order. Finally, click on "Generate ticket" and a txt file will be generated with the summary of the order (right now the ticket is made for the previous version, in which the pizzas were not saved, but the options were chosen and directly printed the ticket).
The problem I have is that when I save the first pizza, everything seems to be fine, but when I save the second pizza, both the first and the second ones happen to have the additional ingredients of the second one. This affects the summary of the order, the price, etc... On the other hand, this does not seem to happen when the first or second pizza does not have additional ingredients.
This is the "Pizza" class
package modelo;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.List;
public class Pizza {
String masa;
String tipo;
String tamanyo;
Boolean bebida;
Boolean gratinada;
ArrayList ingredientes = new ArrayList();
Precios precio = new Precios();
Double precioMasa = 0d;
Double precioTipo = 0d;
Double precioTamanyo = 0d;
Double precioIngredientes = 0d;
Double precioBebida = 0d;
Double precioGratinada = 0d;
public Pizza(String masa, String tipo, String tamanyo, Boolean bebida, Boolean gratinada) {
this.masa = masa;
this.tipo = tipo;
this.tamanyo = tamanyo;
this.bebida = bebida;
this.gratinada = gratinada;
}
public Pizza(){}
public String getMasa() {
return masa;
}
public void setMasa(String masa) {
this.masa = masa;
}
public String getTipo() {
return tipo;
}
public void setTipo(String tipo) {
this.tipo = tipo;
}
public String getTamanyo() {
return tamanyo;
}
public void setTamanyo(String tamanyo) {
this.tamanyo = tamanyo;
}
public ArrayList getIngredientes() {
return ingredientes;
}
public void setIngredientes(ArrayList ingredientes) {
this.ingredientes = ingredientes;
}
public void setBebida(Boolean bebida){
this.bebida = bebida;
}
public Boolean getBebida(){
return bebida;
}
public Boolean getGratinada(){
return gratinada;
}
public void setGratinada(Boolean gratinada){
this.gratinada = gratinada;
}
public Precios getPrecio() {
return precio;
}
public void setPrecio(Precios precio) {
this.precio = precio;
}
public Double calcularPrecio(){
Double precioPizza;
precioIngredientes = 0d;
precioTipo = precio.getPrecioTipo(tipo);
precioMasa = precio.getPrecioMasa(masa);
for(int i = 0; i < ingredientes.size(); i++){
precioIngredientes += precio.getPrecioIngredientes(ingredientes.get(i).toString());
}
precioTamanyo = precio.getPrecioTamanyo(tamanyo);
precioBebida = precio.getPrecioBebida(bebida);
precioGratinada = precio.getPrecioGratinada(gratinada);
precioPizza = (precioMasa + precioTipo + precioIngredientes) * precioTamanyo;
precioPizza *= precioGratinada;
precioPizza += precioBebida;
return precioPizza;
}
public ArrayList composicion(String addStr){
ArrayList<String> str = new ArrayList<>();
String ingr = "";
String strTamanyo = "";
String strBebida;
String strGratinada;
DecimalFormat df = new DecimalFormat("#.##");
Double incrPrecioTamanyo = (precioTamanyo * 100d) - 100d;
Double incrPrecioGratinada = (precioGratinada * 100d) - 100d;
String strPorcentajeTamanyo = String.valueOf(df.format(incrPrecioTamanyo));
String strPorcentajeGratinada = String.valueOf(df.format(incrPrecioGratinada));
for (int i = 0; i < this.ingredientes.size(); i++){
if(i < this.ingredientes.size() - 1){
ingr += this.ingredientes.get(i).toString() + ", ";
}else{
ingr += this.ingredientes.get(i).toString();
}
}
if(this.bebida){
strBebida = "Sí - " + precioBebida;
}else{
strBebida = "No - 0";
}
if(this.gratinada){
strGratinada = "Sí - " + strPorcentajeGratinada;
}else{
strGratinada = "No - 0";
}
strTamanyo = String.valueOf(incrPrecioTamanyo);
str.add("MASA: " + this.masa + " - " + precioMasa + "€");
str.add("TIPO: " + this.tipo + " - " + precioTipo + "€");
str.add("INGREDIENTES: " + ingr + " - " + precioIngredientes + "€");
str.add("TAMAÑO: " + this.tamanyo + " - " + strPorcentajeTamanyo + "%");
str.add("GRATINADA: " + strGratinada + "%");
str.add("BEBIDA: " + strBebida + "€");
str.add(addStr);
return str;
}
}
...And this is the FXMLDocumentController, where I suspect the problem is, although at this point, no idea...
package pizzeria_1.pkg0;
import java.io.BufferedWriter;
import java.io.IOException;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
import java.text.DateFormat;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.ResourceBundle;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.Button;
import javafx.scene.control.CheckBox;
import javafx.scene.control.ComboBox;
import javafx.scene.control.Label;
import javafx.scene.control.ListView;
import javafx.scene.control.RadioButton;
import javafx.scene.control.SelectionMode;
import javafx.scene.control.Spinner;
import javafx.scene.control.SpinnerValueFactory;
import javafx.scene.control.SpinnerValueFactory.ListSpinnerValueFactory;
import javafx.scene.control.TextArea;
import javafx.scene.control.ToggleGroup;
import javafx.scene.input.MouseEvent;
import modelo.Pizza;
import modelo.Precios;
public class FXMLDocumentController implements Initializable {
private final ArrayList listaIngredientes = new ArrayList();
private final ArrayList listaTipos = new ArrayList();
private final ArrayList listaTamanyos = new ArrayList();
private final ArrayList listaMasas = new ArrayList();
private final ArrayList opciones = new ArrayList();
private ArrayList<Pizza> pizzas = new ArrayList();
private String eleccionTipo;
private final ArrayList eleccionIngr = new ArrayList();
private String eleccionTama;
private Boolean eleccionBebida;
private Boolean eleccionGratinada;
private double precioFinal = 0d;
DecimalFormat df = new DecimalFormat("#.##");
private final ObservableList<String> listaObservableIngredientes = FXCollections.observableArrayList();
private final ObservableList<String> listaObservableTipos = FXCollections.observableArrayList();
private final ObservableList<String> listaObservableTamanyos = FXCollections.observableArrayList("Pequeña", "Mediana", "Familiar");
private Pizza miPizza = new Pizza();
@FXML
private Button calcular;
@FXML
private RadioButton masa_normal;
@FXML
private ToggleGroup tg_masa;
@FXML
private RadioButton masa_integral;
@FXML
private ComboBox<String> tipo;
@FXML
private ListView<String> ingredientes;
@FXML
private Spinner<String> tamanyo;
//private TextArea pedido;
private Label precio;
@FXML
private CheckBox bebida;
@FXML
private CheckBox gratinada;
@FXML
private Button generarTicket;
@FXML
private Button addPizza;
@FXML
private TextArea resumenPizza;
@FXML
private Label precioPedido;
@FXML
private Label precioPizza;
@FXML
private TextArea resumenPedido;
@Override
public void initialize(URL url, ResourceBundle rb) {
listaIngredientes.add("jamon");
listaIngredientes.add("queso");
listaIngredientes.add("tomate");
listaIngredientes.add("cebolla");
listaIngredientes.add("olivas");
listaTipos.add("Básica");
listaTipos.add("Cuatro Quesos");
listaTipos.add("Barbacoa");
listaTipos.add("Mexicana");
listaTamanyos.add("Pequeña");
listaTamanyos.add("Mediana");
listaTamanyos.add("Familiar");
listaMasas.add("Normal");
listaMasas.add("Integral");
listaObservableIngredientes.addAll(listaIngredientes);
ingredientes.setItems(listaObservableIngredientes);
ingredientes.getSelectionModel().setSelectionMode(SelectionMode.MULTIPLE);
listaObservableTipos.addAll(listaTipos);
tipo.setItems(listaObservableTipos);
ListSpinnerValueFactory<String> tamanyos = new SpinnerValueFactory.ListSpinnerValueFactory(listaObservableTamanyos);
tamanyo.setValueFactory(tamanyos);
calcular.setVisible(false);
calcularPizza();
}
@FXML
public void calcularPizza(){
clearPizza();
eligeMasa();
eligeTipo();
eligeIngredientes();
eligeTamanyo();
eligeBebida();
eligeGratinada();
escribirPrecioPizza();
escribirPizza();
}
public void escribirPizza(){
ArrayList<String> comp = miPizza.composicion("");
String out = "";
for(int j = 0; j< comp.size(); j++){
out += comp.get(j) + "\n";
}
resumenPizza.appendText(out);
}
public void clearPizza(){
resumenPizza.setText("");
eleccionIngr.clear();
}
public void calcularPrecioPedido(){
for(int i = 0; i < pizzas.size(); i++){
precioFinal += pizzas.get(i).calcularPrecio();
}
precioPedido.setText(String.valueOf(precioFinal));
}
public void escribirPedido(){
ArrayList<String> comp = new ArrayList<>();
String out = "";
for(int i = 0; i < pizzas.size(); i++){
System.out.println(pizzas.get(i).getIngredientes());
System.out.println("-");
out += "Pizza #" + String.valueOf(i+1) + "\n";
comp = pizzas.get(i).composicion("");
for(int j = 0; j< comp.size(); j++){
out += comp.get(j) + "\n";
}
}
resumenPedido.appendText(out);
}
public void clearPedido(){
resumenPedido.setText("");
ingredientes.getSelectionModel().clearSelection();
bebida.setSelected(false);
gratinada.setSelected(false);
masa_normal.setSelected(true);
masa_integral.setSelected(false);
tamanyo.getValueFactory().setValue("Pequeña");
tipo.setValue("Básica");
precioFinal = 0;
}
@FXML
private void addPizza(ActionEvent event) {
pizzas.add(miPizza); //Añado la pizza actual al arraylist
miPizza = new Pizza(); //creo una nueva pizza
calcularPrecioPedido(); //calculo el precio total de las pizzas del arraylist
clearPedido(); //limpio el texto del pedido
escribirPedido(); //y ahora lo escribo con las pizzas del arraylist
clearPizza(); //pongo los campos del formulario por defecto
calcularPizza(); //calculo la seleccion actual
}
@FXML
private void generarTicket(ActionEvent event) {
String str = "";
ArrayList<String> comp = miPizza.composicion("");
String precioTotal = String.valueOf(miPizza.calcularPrecio());
Date fecha = Calendar.getInstance().getTime();
DateFormat df = new SimpleDateFormat("dd-mm-yy_hh-mm-ss");
String fechaStr = df.format(fecha);
String nombreArchivo = "src/tickets/Ticket-" + fechaStr + ".txt";
//String nombreArchivo = "src/tickets/archivo.txt";
Path archivo = Paths.get(nombreArchivo);
try(BufferedWriter bw = Files.newBufferedWriter(archivo, StandardCharsets.UTF_8, StandardOpenOption.CREATE)){
for(int i = 0; i< comp.size(); i++){
bw.write(comp.get(i));
bw.newLine();
}
bw.write("Precio Total: " + precioTotal + "€");
}catch(IOException e){
miPizza.composicion("\n\nError al crear el ticket.");
}
}
public void escribirPrecioPizza(){
precioPizza.setText(String.valueOf(miPizza.calcularPrecio())+"€");
}
public void eligeMasa() {
if(masa_normal.isSelected()){
miPizza.setMasa("Normal");
}else if(masa_integral.isSelected()){
miPizza.setMasa("Integral");
}else{
miPizza.setMasa("Normal");
masa_normal.setSelected(true);
}
}
public void eligeTipo(){
eleccionTipo = tipo.getValue();
if(eleccionTipo != null){
miPizza.setTipo(eleccionTipo);
}else{
miPizza.setTipo("Básica");
tipo.getSelectionModel().select("Básica");
}
}
public void eligeIngredientes(){
eleccionIngr.clear();
for (String str : ingredientes.getSelectionModel().getSelectedItems()) {
if(str != null){
eleccionIngr.add(str);
}
}
if(eleccionIngr.size() > 0){
miPizza.setIngredientes(eleccionIngr);
}
}
public void eligeTamanyo(){
eleccionTama = tamanyo.getValue();
if(eleccionTama != null){
miPizza.setTamanyo(eleccionTama);
}
}
public void eligeGratinada(){
eleccionGratinada = gratinada.selectedProperty().getValue();
miPizza.setGratinada(eleccionGratinada);
}
public void eligeBebida(){
eleccionBebida = bebida.selectedProperty().getValue();
miPizza.setBebida(eleccionBebida);
}
}
In order not to copy the rest of the code here, I leave a link to the entire project , in case it helps in any way.
Edito: Por si sirve de algo, aqui muestro como elijo una primera pizza con extra de "Jamón" y al añador al pedido una segunda pizza con Extra de "Cebolla", ahora las dos parecen tener extra de "Cebolla" y ni rastro del "Jamón":
El problema por el cual se muestran los ingredientes extras al agregar una nueva pizza se debe a que en el metodo
addPizza()
debes crear una nueva instancia dePizza
antes de agregarla a el arraypizzas
, de esta formaAl pasar como parámetro una colección a otro bjeto (como en el cao de los ingredientes), se pasa la dirección de memoria, y no los datos en sí. La solución pasa por volver a crear una colección nueva para los nuevos elementos, de una de las siguientes maneras:
La respuesta es de mi profesora, no quisiera atribuirme un mérito que no me corresponde, pero en cualquier caso, problema resuelto y ojalá que pueda ayudar a otros en algún momento.
A @Jorgesys, muchas gracias por el interés!