Last active
December 19, 2015 17:49
-
-
Save jsianes/5994066 to your computer and use it in GitHub Desktop.
This Java code helps you to analyze economic proposals of a contest according to art.85 hiring law of Public Administrations in Spain (Real Decreto 1098/2001,Reglamento LCAP - artículo 85: http://is.gd/uANADN )
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import java.io.*; | |
import java.util.*; | |
import java.text.*; | |
public class LCAP { | |
public static void Ley() { | |
System.out.printf("Evaluacion segun la LCAP:\n\n"+ | |
"Articulo 85. Criterios para apreciar las ofertas desproporcionadas o temerarias en las\n"+ | |
"subastas.- Se consideraran, en principio, desproporcionadas o temerarias las ofertas que\n"+ | |
"se encuentren en los siguientes supuestos:\n\n"+ | |
"1. Cuando, concurriendo un solo licitador, sea inferior al presupuesto base de licitacion en\n"+ | |
" mas de 25 unidades porcentuales.\n"+ | |
"2. Cuando concurran dos licitadores, la que sea inferior en mas de 20 unidades\n"+ | |
" porcentuales a la otra oferta.\n"+ | |
"3. Cuando concurran tres licitadores, las que sean inferiores en mas de 10 unidades\n"+ | |
" porcentuales a la media aritmetica de las ofertas presentadas. No obstante, se excluira para\n"+ | |
" el computo de dicha media la oferta de cuantia mas elevada cuando sea superior en mas\n"+ | |
" de 10 unidades porcentuales a dicha media. En cualquier caso, se considerara\n"+ | |
" desproporcionada la baja superior a 25 unidades porcentuales.\n"+ | |
"4. Cuando concurran cuatro o mas licitadores, las que sean inferiores en mas de 10\n"+ | |
" unidades porcentuales a la media aritmetica de las ofertas presentadas. No obstante, si\n"+ | |
" entre ellas existen ofertas que sean superiores a dicha media en mas de 10 unidades\n"+ | |
" porcentuales, se procedera al calculo de una nueva media solo con las ofertas que no se\n"+ | |
" encuentren en el supuesto indicado. En todo caso, si el numero de las restantes ofertas es\n"+ | |
" inferior a tres, la nueva media se calculara sobre las tres ofertas de menor cuantia.\n"+ | |
"5. Excepcionalmente, y atendiendo al objeto del contrato y circunstancias del mercado, el\n"+ | |
" organo de contratacion podra motivadamente reducir en un tercio en el correspondiente\n"+ | |
" pliego de clausulas administrativas particulares los porcentajes establecidos en los\n"+ | |
" apartados anteriores.\n"+ | |
"6. Para la valoracion de la ofertas como desproporcionadas, la mesa de contratacion\n"+ | |
" podra considerar la relacion entre la solvencia de la empresa y la oferta presentada.\n\n"); | |
} | |
public static void mensajeAyuda() { | |
System.out.println(""); | |
System.out.println("Uso:"); | |
System.out.println(""); | |
System.out.println(" java -jar LCAP.jar ley"); | |
System.out.println(" - Muestra la informacion de la ley relativa al articulo 85 de la LCAP"); | |
System.out.println(""); | |
System.out.println(" java -jar LCAP.jar PresupuestoBase escala aceptarBajas fichero.csv"); | |
System.out.println(""); | |
System.out.println("Donde:"); | |
System.out.println(" - PresupuestoBase: Es el presupuesto base en euros de licitacion"); | |
System.out.println(" - escala: Numero entero mayor que 0 que indica la escala sobre la que puntuar"); | |
System.out.println(" evaluandose los licitadores con puntuacion de 0 y el valor de la escala"); | |
System.out.println(" - aceptarBajar: valor entero binario: 0 indica que no se deben tener en consideracion"); | |
System.out.println(" las bajas temerarias y 1 que si deben tenerse en consideracion en la evaluacion"); | |
System.out.println(" - 'fichero.csv' nombre del fichero CSV de entrada que contiene por cada linea"); | |
System.out.println(" el nombre del licitador y la oferta economica presentada, ambos valores separados"); | |
System.out.println(" por el caracter \';\'. La oferta economica debe ir expresada en notacion decimal"); | |
System.out.println(" americana, es decir, el caracter \'.\' debe usarse para separar los decimales"); | |
System.out.println(""); | |
System.out.println(" Ejemplo:"); | |
System.out.println(""); | |
System.out.println(" Oferta 1;10000"); | |
System.out.println(" Oferta 2;12500.25"); | |
System.out.println(" Oferta 3;20000.5"); | |
System.out.println(" Oferta 4;20000.95"); | |
System.out.println(" Oferta 5;21100"); | |
System.out.println(""); | |
System.out.println("Copyleft 2013 - Javier Sianes ([email protected])"); | |
System.out.println(""); | |
System.exit(1); | |
} | |
public static void main(String[] args) { | |
DecimalFormat df = new DecimalFormat("#.##"); | |
int escala=0,aceptarBajas=0,lineas=0; | |
double presupuestoBase=0.0; | |
if (args.length<=3) {if (args.length==1) {Ley();} else {mensajeAyuda();}} | |
try { | |
presupuestoBase=Double.parseDouble(args[0]); | |
escala=Integer.parseInt(args[1]); | |
aceptarBajas=Integer.parseInt(args[2]); | |
}catch(NumberFormatException e) {System.exit(3);} | |
File f = new File(args[3]); | |
if(f.exists()) { | |
try{ | |
LineNumberReader lnr = new LineNumberReader(new FileReader(new File(args[3]))); | |
lnr.skip(Long.MAX_VALUE); | |
lineas=lnr.getLineNumber(); | |
lnr.close(); | |
System.out.println("-- El fichero \""+args[3]+"\",en base al numero de lineas, contiene "+lineas+" potenciales licitadores"); | |
if (aceptarBajas==1) { | |
System.out.println("-- Se aceptan a evaluacion las bajas temerarias"); | |
} else { | |
System.out.println("-- No se aceptan a evalucion las bajas temerarias"); | |
} | |
FileInputStream fstream = new FileInputStream(args[3]); | |
DataInputStream in = new DataInputStream(fstream); | |
BufferedReader br = new BufferedReader(new InputStreamReader(in)); | |
String line; | |
Double value=0.0; | |
Vector<Licitador> v = new Vector<Licitador>(); | |
while ((line = br.readLine())!=null) { | |
String[] linea = line.split(";"); | |
if (linea.length==2) { | |
try | |
{ | |
if (!linea[0].isEmpty()) { | |
value=Double.parseDouble(linea[1]); | |
Licitador l = new Licitador(linea[0],value); | |
if (!ofertanteExiste(v,l)) { | |
if (l.oferta<=presupuestoBase) {v.add(l);} else { | |
System.out.println("-- Descartado licitador \""+l.licitador+"\" por exceder su oferta ("+l.oferta+") el presupuesto base ("+presupuestoBase+")"); | |
} | |
} else { | |
System.out.println("-- Eliminada la oferta del licitador \""+l.licitador+"\" ("+df.format(l.oferta)+") por duplicidad"); | |
} | |
} | |
}catch(NumberFormatException e) {} | |
} | |
} | |
in.close(); | |
switch (v.size()) { | |
case 0: | |
System.out.println("-- ERROR: No existen ofertas que cumplan los criterios de valoracion indicados."); | |
System.out.println(""); | |
System.exit(2); | |
break; | |
case 1: | |
puntuacion1Licitador(presupuestoBase, escala, aceptarBajas, v); | |
break; | |
case 2: | |
puntuacion2Licitadores(presupuestoBase, escala, aceptarBajas, v); | |
break; | |
case 3: | |
puntuacion3Licitadores(presupuestoBase, escala, aceptarBajas, v); | |
break; | |
default: | |
puntuacion4omasLicitadores(presupuestoBase, escala, aceptarBajas, v); | |
break; | |
} | |
}catch (Exception e){ | |
System.err.println("Error: " + e.getMessage()); | |
System.exit(255); | |
} | |
} | |
} | |
public static void puntuacion1Licitador(double presupuestoBase, int escala, int aceptarBajas, Vector<Licitador> v) { | |
DecimalFormat df = new DecimalFormat("#.##"); | |
double bajaTemeraria=0.0; | |
System.out.println("-- Un licitador valido: aplicando norma de LCAP para un licitador"); | |
System.out.println("-- Presupuesto base: "+df.format(presupuestoBase)); | |
bajaTemeraria=0.75*presupuestoBase; | |
muestraResultados(bajaTemeraria, presupuestoBase, escala, aceptarBajas, v); | |
} | |
public static void puntuacion2Licitadores(double presupuestoBase, int escala, int aceptarBajas, Vector<Licitador> v) { | |
DecimalFormat df = new DecimalFormat("#.##"); | |
double bajaTemeraria=0.0; | |
System.out.println("-- Dos licitadores validos: aplicando norma de LCAP para dos licitadores"); | |
System.out.println("-- Presupuesto base: "+df.format(presupuestoBase)); | |
if (v.get(0).oferta>=v.get(1).oferta) {bajaTemeraria=0.8*v.get(0).oferta;}else{bajaTemeraria=0.8*v.get(1).oferta;} | |
muestraResultados(bajaTemeraria, presupuestoBase, escala, aceptarBajas, v); | |
} | |
public static void puntuacion3Licitadores(double presupuestoBase, int escala, int aceptarBajas, Vector<Licitador> v) { | |
DecimalFormat df = new DecimalFormat("#.##"); | |
double bajaTemeraria=0.0,promedio=0.0,suma=0.0,max=0.0; | |
for (int i=0;i<v.size();i++) { | |
suma=suma+v.get(i).oferta; | |
if ((v.get(i).oferta)>max) {max=v.get(i).oferta;} | |
} | |
promedio=suma/v.size(); | |
System.out.println("-- Tres licitadores: aplicando norma de LCAP para tres licitadores"); | |
System.out.println("-- Presupuesto base: "+df.format(presupuestoBase)); | |
System.out.println("-- Promedio de las tres ofertas: "+df.format(promedio)); | |
if (max>(promedio*1.1)) { | |
promedio=(suma-max)/((v.size())-1); | |
System.out.println("-- La mayor oferta ("+df.format(max)+") supera en 10 puntos porcentuales al promedio, recalculando promedio sin dicha oferta"); | |
System.out.println("-- Nuevo promedio: "+df.format(promedio)); | |
} | |
bajaTemeraria=0.75*promedio; | |
muestraResultados(bajaTemeraria, presupuestoBase, escala, aceptarBajas, v); | |
} | |
public static void puntuacion4omasLicitadores(double presupuestoBase, int escala, int aceptarBajas, Vector<Licitador> v) { | |
DecimalFormat df = new DecimalFormat("#.##"); | |
int j=0,k=0,total=v.size(); | |
double bajaTemeraria=0.0,promedio=0.0,suma=0.0,max=0.0; | |
for (int i=0;i<v.size();i++) { | |
suma=suma+v.get(i).oferta; | |
if ((v.get(i).oferta)>max) {max=v.get(i).oferta;} | |
} | |
promedio=suma/v.size(); | |
System.out.println("-- Cuatro o mas licitadores: aplicando norma de LCAP para cuatro o mas licitadores"); | |
System.out.println("-- Presupuesto base: "+df.format(presupuestoBase)); | |
System.out.println("-- Promedio de las "+total+" ofertas: "+df.format(promedio)); | |
for (int i=0;i<v.size();i++) { | |
if ((v.get(i).oferta)>(promedio*1.1)) { | |
System.out.println("-- La oferta del licitador \""+v.get(i).licitador+"\" excede en 10 puntos porcentuales la media ("+df.format(v.get(i).oferta)+")"); | |
j++; | |
} | |
} | |
System.out.println("-- Del total de "+total+" ofertas hay "+j+" ofertas que exceden en 10 puntos porcentuales el promedio "); | |
if ((total-j)<3) { | |
System.out.println("-- Se usaran las 3 ofertas de menor valor para recalcular el promedio"); | |
List<Double> w = new Vector<Double>(total); | |
for (int i=0;i<v.size();i++) { | |
w.add(v.get(i).oferta); | |
} | |
Collections.sort(w); | |
promedio=(w.get(0)+w.get(1)+w.get(2))/3; | |
System.out.println("-- Promedio con las tres ofertas mas bajas: "+df.format(promedio)); | |
} else { | |
System.out.println("-- Se usaran las ofertas que no exceden para recalcular el promedio"); | |
suma=0.0; | |
for (int i=0;i<v.size();i++) { | |
if ((v.get(i).oferta)<=(promedio*1.1)) { | |
suma=suma+v.get(i).oferta; | |
k++; | |
} | |
} | |
promedio=(suma/k); | |
System.out.println("-- Nuevo promedio empleando estas "+k+" ofertas: "+df.format(promedio)); | |
} | |
bajaTemeraria=0.9*promedio; | |
muestraResultados(bajaTemeraria, presupuestoBase, escala, aceptarBajas, v); | |
} | |
public static boolean ofertanteExiste(Vector<Licitador> v, Licitador l) { | |
Iterator<Licitador> itr = v.iterator(); | |
while(itr.hasNext()) { | |
Licitador k = itr.next(); | |
if (l.licitador.toLowerCase().equals(k.licitador.toLowerCase())) {return true;} | |
} | |
return false; | |
} | |
public static void muestraResultados(double bajaTemeraria, double presupuestoBase, int escala, int aceptarBajas, Vector<Licitador> v) { | |
String baja=""; | |
int j=0,indexGanadora=0; | |
double max=0.0,min=0.0,punt=0.0; | |
DecimalFormat df = new DecimalFormat("#.##"); | |
System.out.println("-- Se puntuaran las ofertas con \'0\' como valor minimo y \'"+escala+"\' como valor maximo"); | |
System.out.println("-- Baja temeraria: "+df.format(bajaTemeraria)); | |
for (int i=0;i<v.size();i++) { | |
if ((v.get(i).oferta)>max) {max=v.get(i).oferta;} | |
if (i==0) {min=v.get(i).oferta;} else {if (v.get(i).oferta<min) {min=v.get(i).oferta;}} | |
if (v.get(i).oferta<bajaTemeraria) {v.get(i).enBajaTemeraria=true;} | |
} | |
if (aceptarBajas==0) { | |
j=0; | |
while (j<v.size()) { | |
if (v.get(j).enBajaTemeraria) { | |
System.out.println("-- Oferta del licitador \""+v.get(j).licitador+"\" eliminada por estar en baja temeraria ("+df.format(v.get(j).oferta)+")"); | |
v.remove(j); | |
j=0; | |
} else { | |
j++; | |
} | |
} | |
} | |
if (presupuestoBase>max) {max=presupuestoBase;} | |
if (aceptarBajas==0) {min=bajaTemeraria;} | |
for (int i=0;i<v.size();i++) { | |
v.get(i).puntuacion=(((max-v.get(i).oferta)*escala)/(max-min)); | |
if (v.get(i).puntuacion>punt) {punt=v.get(i).puntuacion;indexGanadora=(i+1);} | |
} | |
if (indexGanadora!=0) { | |
System.out.println("-- Indice de la oferta ganadora: "+indexGanadora); | |
System.out.println(""); | |
System.out.println("Indice;Licitador;Baja;Oferta;Puntuacion"); | |
for (int i=0;i<v.size();i++) { | |
if (v.get(i).oferta<bajaTemeraria) {baja="Si";}else{baja="No";} | |
System.out.println((i+1)+";"+v.get(i).licitador+";"+baja+";"+df.format(v.get(i).oferta)+";"+df.format(v.get(i).puntuacion)); | |
} | |
} else { | |
System.out.println("-- No existe ninguna oferta que cumpla los requisitos"); | |
} | |
System.out.println(""); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class Licitador { | |
public String licitador; | |
public double oferta; | |
public boolean enBajaTemeraria; | |
public double puntuacion; | |
public Licitador(String name, double value) { | |
this.licitador=name; | |
this.oferta=value; | |
this.enBajaTemeraria=false; | |
this.puntuacion=0.0; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment