/* * UFO Saved Game Editor * Copyright (C) 2010 Christopher Davoren * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package net.rubikscomplex.ufosge.gui.table; import java.util.ArrayList; import java.util.Iterator; import java.util.Map; import javax.swing.table.AbstractTableModel; import net.rubikscomplex.ufosge.UFOInfo; import net.rubikscomplex.ufosge.data.Facility; import net.rubikscomplex.ufosge.data.ProducibleItem; import net.rubikscomplex.ufosge.data.Research; import net.rubikscomplex.ufosge.data.SavedGame; import net.rubikscomplex.ufosge.data.UPItem; /** * * @author Chris Davoren */ public class ResearchTableModel extends AbstractTableModel { public static final int COLUMN_NAME = 0; public static final int COLUMN_TIME_REQUIRED = 1; public static final int COLUMN_AVAILABLE = 2; public static final int COLUMN_RESEARCHED = 3; protected SavedGame game; protected ArrayList<Research> researchCache; protected ArrayList<UPItem> upCache; protected ArrayList<Facility> facilityCache; protected ArrayList<ProducibleItem> itemCache; protected Map<String, String[]> rpr = UFOInfo.researchPrerequisites(); protected Map<String, String[]> ipr = UFOInfo.itemPrerequisiteMap(); public ResearchTableModel(SavedGame game, ArrayList<Research> rCache, ArrayList<Facility> fCache, ArrayList<ProducibleItem> pCache, ArrayList<UPItem> uCache) { super(); this.game = game; setCache(rCache, fCache, pCache, uCache); } public void setCache(ArrayList<Research> rCache, ArrayList<Facility> fCache, ArrayList<ProducibleItem> pCache, ArrayList<UPItem> uCache) { researchCache = rCache; facilityCache = fCache; itemCache = pCache; upCache = uCache; fireTableDataChanged(); } public Object getValueAt(int row, int column) { switch(column) { case COLUMN_NAME: return Research.PROJECT_NAMES[researchCache.get(row).index]; case COLUMN_TIME_REQUIRED: return researchCache.get(row).time; case COLUMN_RESEARCHED: return researchCache.get(row).completed; case COLUMN_AVAILABLE: return researchCache.get(row).prerequisitesMet; default: return null; } } @Override public void setValueAt(Object value, int row, int column) { // System.out.println("Setting value at " + row + ", " + column); if (column != COLUMN_RESEARCHED && column != COLUMN_AVAILABLE) { return; } boolean val = ((Boolean)value).booleanValue(); if (column == COLUMN_RESEARCHED) { Research rc = researchCache.get(row); updateResearchItem(rc, val); } else if (column == COLUMN_AVAILABLE) { Research rc = researchCache.get(row); if (val) { rc.completed = false; rc.prerequisitesMet = true; } else { rc.prerequisitesMet = false; } } } protected void updateResearchItem(Research rc, boolean completed) { // System.out.println("Updating research item: " + rc.index); rc.completed = completed; /* Make UFOpaedia article available */ Iterator<UPItem> ui = upCache.iterator(); while(ui.hasNext()) { UPItem uc = ui.next(); if (uc.category == rc.UFOpaediaCategory && uc.nameIndex == rc.UFOpaediaEntry) { if (uc.researchFlag != UPItem.RESEARCH_ALWAYS) { // System.out.println("Updating UFOpaedia entry " + uc.index + " (" + UPItem.CATEGORIES[uc.category] + ", " + UPItem.SUBCATEGORIES[uc.category][uc.subCategory] + ")"); if (completed) { uc.researchFlag = UPItem.RESEARCH_DONE; } else if (!(rc.isLiveAlien() && Research.otherResearchForRaceCompleted(rc, researchCache))) { uc.researchFlag = UPItem.RESEARCH_NOT_YET; } } } } /* If the research refers to a base facility, make it buildable */ for(int i = 0; i < Facility.FACILITY_NAMES.length; i++) { if (Research.PROJECT_NAMES[rc.index].equals(Facility.FACILITY_NAMES[i])) { // System.out.println("Updating facility " + Facility.FACILITY_NAMES[i] + ": " + completed); // System.out.println("Index: " + facilityCache.get(i).index); facilityCache.get(i).buildable = completed; facilityCache.get(i).requiresResearch = !completed; break; } } // System.out.println("Changing research for research " + Research.PROJECT_NAMES[rc.index]); boolean changed = true; /* Update prerequisite status of ALL research topics */ while(changed) { changed = false; Iterator<Research> ri = researchCache.iterator(); while(ri.hasNext()) { Research rcc = ri.next(); String[] rccPrerequisites = rpr.get(Research.PROJECT_NAMES[rcc.index]); if (rccPrerequisites == null) { /* This flag is always true for items with no research prerequisites */ rcc.prerequisitesMet = true; continue; } boolean pm = true; for(int i = 0; i < rccPrerequisites.length; i++) { Iterator<Research> rii = researchCache.iterator(); while(rii.hasNext()) { Research rcp = rii.next(); if (Research.PROJECT_NAMES[rcp.index].equals(rccPrerequisites[i])) { // System.out.println("Updating a prerequisite for research " + Research.PROJECT_NAMES[rcc.index] + ": " + Research.PROJECT_NAMES[rcp.index]); pm &= rcp.completed; } } } // If the research has already been completed, assume pre-requisites met pm = pm || rcc.completed; changed = rcc.prerequisitesMet != pm; /* if (changed) { System.out.println("Research availability for " + Research.PROJECT_NAMES[rcc.index] + " is now: " + pm); } */ rcc.prerequisitesMet = pm; fireTableCellUpdated(rcc.index, COLUMN_AVAILABLE); } } /* Update buildable status of ALL items */ // System.out.println("Changing items for research item " + Research.PROJECT_NAMES[rc.index]); changed = true; while (changed) { changed = false; Iterator<ProducibleItem> pi = itemCache.iterator(); while(pi.hasNext()) { ProducibleItem pc = pi.next(); String[] itemPrerequisites = ipr.get(ProducibleItem.ITEM_NAMES[pc.index]); if (itemPrerequisites == null) { continue; } boolean pm = true; for(int i = 0; i < itemPrerequisites.length; i++) { Iterator<Research> iri = researchCache.iterator(); while(iri.hasNext()) { Research rcc = iri.next(); if (itemPrerequisites[i].equals(Research.PROJECT_NAMES[rcc.index])) { // System.out.println("Updating a prerequisite for item " + ProducibleItem.ITEM_NAMES[pc.index] + ": " + Research.PROJECT_NAMES[rcc.index]); pm &= rcc.completed; } } } changed = pc.buildable != pm; /* if (changed) { System.out.println("Buildability for item " + ProducibleItem.ITEM_NAMES[pc.index] + " is now: " + pm); } */ pc.buildable = pm; } } if (UFOInfo.processSpecialResearchRequirements(researchCache)) { fireTableDataChanged(); } } public void completeAll() { Iterator<Research> ri = researchCache.iterator(); while(ri.hasNext()) { Research rc = ri.next(); // updateResearchItem(rc, true); rc.prerequisitesMet = true; if (!rc.isLiveAlien()) { rc.completed = true; } } /* Ensure that all races, alien ships and alien missions are available in the UFOpaedia */ Iterator<UPItem> upi = upCache.iterator(); while(upi.hasNext()) { UPItem up = upi.next(); /* if((up.category == 5 || up.category == 6 || up.category == 8) && up.researchFlag != UPItem.RESEARCH_ALWAYS) { up.researchFlag = UPItem.RESEARCH_DONE; } */ if(up.researchFlag != UPItem.RESEARCH_ALWAYS) { up.researchFlag = UPItem.RESEARCH_DONE; } } Iterator<Facility> fi = facilityCache.iterator(); while(fi.hasNext()) { Facility f = fi.next(); f.buildable = true; } Iterator<ProducibleItem> pii = itemCache.iterator(); while(pii.hasNext()) { ProducibleItem pi = pii.next(); pi.buildable = true; } fireTableDataChanged(); } public int getColumnCount() { return 4; } public int getRowCount() { return researchCache.size(); } @Override public String getColumnName(int column) { switch(column) { case COLUMN_NAME: return "Project Name"; case COLUMN_TIME_REQUIRED: return "Time Required"; case COLUMN_RESEARCHED: return "Completed"; case COLUMN_AVAILABLE: return "Available"; default: return "Unknown"; } } @Override public boolean isCellEditable(int row, int column) { // System.out.println("Cell editable (" + column + ")"); return !researchCache.get(row).isLiveAlien() && (column == COLUMN_RESEARCHED || column == COLUMN_AVAILABLE); } @Override public Class<?> getColumnClass(int column) { switch(column) { case COLUMN_NAME: return String.class; case COLUMN_TIME_REQUIRED: return Integer.class; case COLUMN_RESEARCHED: return Boolean.class; case COLUMN_AVAILABLE: return Boolean.class; default: return Object.class; } } }