Skip to content

Instantly share code, notes, and snippets.

@fero23
Last active August 20, 2016 20:18
Show Gist options
  • Save fero23/b81362947cc211a1bcccb650b3617853 to your computer and use it in GitHub Desktop.
Save fero23/b81362947cc211a1bcccb650b3617853 to your computer and use it in GitHub Desktop.
Creador de presupuestos en Rust on the fly
use std::io::{self, Write};
use std::fs::File;
use std::path::Path;
use std::rc::Rc;
use std::cmp;
use std::collections::HashMap;
enum TableCell {
TableHeader {
content: String,
rowspan: Option<usize>,
colspan: Option<usize>
},
TableData {
content: String,
rowspan: Option<usize>,
colspan: Option<usize>
},
EmptyCell {
rowspan: Option<usize>,
colspan: Option<usize>
}
}
impl TableCell {
fn to_html(&self) -> String {
match *self {
TableCell::TableHeader { ref content, rowspan: Some(rowspan), colspan: Some(colspan) } => {
format!(r#"<th rowspan="{}" colspan="{}">{}</th>"#, rowspan, colspan, content)
}
TableCell::TableHeader { ref content, rowspan: Some(rowspan), .. } => {
format!(r#"<th rowspan="{}">{}</th>"#, rowspan, content)
}
TableCell::TableHeader { ref content, colspan: Some(colspan), .. } => {
format!(r#"<th colspan="{}">{}</th>"#, colspan, content)
}
TableCell::TableHeader { ref content, .. } => {
format!(r#"<th>{}</th>"#, content)
}
TableCell::TableData { ref content, rowspan: Some(rowspan), colspan: Some(colspan) } => {
format!(r#"<td rowspan="{}" colspan="{}">{}</td>"#, rowspan, colspan, content)
}
TableCell::TableData { ref content, rowspan: Some(rowspan), .. } => {
format!(r#"<td rowspan="{}">{}</td>"#, rowspan, content)
}
TableCell::TableData { ref content, colspan: Some(colspan), .. } => {
format!(r#"<td colspan="{}">{}</td>"#, colspan, content)
}
TableCell::TableData { ref content, .. } => {
format!(r#"<td>{}</td>"#, content)
}
TableCell::EmptyCell { rowspan: Some(rowspan), colspan: Some(colspan) } => {
format!(r#"<td rowspan="{}" colspan="{}"></td>"#, rowspan, colspan)
}
TableCell::EmptyCell { rowspan: Some(rowspan), .. } => {
format!(r#"<td rowspan="{}"></td>"#, rowspan)
}
TableCell::EmptyCell { colspan: Some(colspan), .. } => {
format!(r#"<td colspan="{}"></td>"#, colspan)
}
TableCell::EmptyCell {..} => {
format!(r#"<td></td>"#)
}
}
}
}
type Row = Vec<TableCell>;
struct Table(Vec<Row>);
impl Table {
fn to_html(&self) -> String {
let table_body = self.0.iter().map(|row| {
format!("<tr>{}</tr>", row.iter().map(|cell| cell.to_html()).collect::<Vec<_>>().concat())
}).collect::<Vec<_>>().concat();
format!("<table>{}</table>", table_body)
}
}
struct Html(Vec<Table>);
impl Html {
fn to_html(&self) -> String {
format!(r#"
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<style>
table {{
margin: 10px;
}}
table, th, td {{
border: 1px solid black;
border-collapse: collapse;
}}
th, td {{
padding: 5px;
text-align: left;
max-width: 120px;
}}
</style>
</head>
<body>{}</body>
</html>"#,
self.0.iter()
.map(|tb| tb.to_html())
.collect::<Vec<_>>()
.concat())
}
fn save_to<P: AsRef<Path>>(&self, path: P) -> io::Result<()> {
let mut file = try!(File::create(path));
try!(file.write_all(self.to_html().as_bytes()));
Ok(())
}
}
#[derive(Clone)]
struct Costo {
cantidad: u32,
producto: String,
precio_unitario: f64
}
impl Costo {
fn get_total(&self) -> f64 {
self.cantidad as f64 * self.precio_unitario
}
}
struct Tarea {
nombre: String,
dur: u32,
materiales: Vec<Costo>,
mano_obra: Vec<Costo>,
costos_indirectos: Vec<Costo>
}
impl Tarea {
fn new(nombre: String, dur: u32) -> Tarea {
Tarea {
nombre: nombre,
dur: dur,
materiales: Vec::new(),
mano_obra: Vec::new(),
costos_indirectos: Vec::new()
}
}
fn add_materiales(&mut self, material: Costo) {
self.materiales.push(material);
}
fn add_mano_obra(&mut self, mano_obra: Costo) {
self.mano_obra.push(mano_obra);
}
fn add_costo_indirecto(&mut self, costo_indirecto: Costo) {
self.costos_indirectos.push(costo_indirecto);
}
fn add_mano_obra_from_builders(&mut self, builders: &[Rc<Fn(u32, f64, f64, f64) -> Costo>]) {
for builder in builders {
let costo = (builder)(self.dur,
self.get_total_materiales(),
self.get_total_mano_obra(),
self.get_total_costo_indirectos());
self.add_mano_obra(costo);
}
}
fn add_costo_indirecto_from_builders(&mut self, builders: &[Rc<Fn(u32, f64, f64, f64) -> Costo>]) {
for builder in builders {
let costo = (builder)(self.dur,
self.get_total_materiales(),
self.get_total_mano_obra(),
self.get_total_costo_indirectos());
self.add_costo_indirecto(costo);
}
}
fn get_total_materiales(&self) -> f64 {
self.materiales.iter().map(|c| c.get_total()).sum()
}
fn get_total_mano_obra(&self) -> f64 {
self.mano_obra.iter().map(|c| c.get_total()).sum()
}
fn get_total_costo_indirectos(&self) -> f64 {
self.costos_indirectos.iter().map(|c| c.get_total()).sum()
}
fn get_max_row(&self) -> usize {
cmp::max(self.materiales.len(), cmp::max(self.mano_obra.len(), self.costos_indirectos.len()))
}
fn get_presupuesto(&self) -> Presupuesto {
let mut presupuesto = Presupuesto::new();
for material in &self.materiales {
presupuesto.add_costo(Presupuesto::material(), material);
}
for mano_obra in &self.mano_obra {
presupuesto.add_costo(Presupuesto::mano_obra(), mano_obra);
}
for costo_indirecto in &self.costos_indirectos {
presupuesto.add_costo(Presupuesto::costo_indirecto(), costo_indirecto);
}
presupuesto
}
}
struct Actividad {
nombre: String,
tareas: Vec<Tarea>
}
impl Actividad {
fn add_mano_obra_from_builders(&mut self, builders: &[Rc<Fn(u32, f64, f64, f64) -> Costo>]) {
for task in &mut self.tareas {
task.add_mano_obra_from_builders(builders);
}
}
fn add_costo_indirecto_from_builders(&mut self, builders: &[Rc<Fn(u32, f64, f64, f64) -> Costo>]) {
for task in &mut self.tareas {
task.add_costo_indirecto_from_builders(builders);
}
}
fn get_dur_total(&self) -> u32 {
self.tareas.iter().map(|task| task.dur).sum()
}
fn get_total_materiales(&self) -> f64 {
self.tareas.iter().map(|task| task.get_total_materiales()).sum()
}
fn get_total_mano_obra(&self) -> f64 {
self.tareas.iter().map(|task| task.get_total_mano_obra()).sum()
}
fn get_total_costo_indirectos(&self) -> f64 {
self.tareas.iter().map(|task| task.get_total_costo_indirectos()).sum()
}
fn get_presupuesto(&self) -> Option<Presupuesto> {
self.tareas.iter().map(|task| task.get_presupuesto()).fold(None, |p1, p2| {
match p1 {
Some(p1) => Some(p1.merge(p2)),
None => Some(p2)
}
})
}
fn get_rows(&self) -> Vec<Row> {
let total_rows = self.tareas.iter().map(|task| task.get_max_row() + 1).sum();
self.tareas.iter().enumerate().flat_map(|(i1, task)| {
let mut materiales_iter = task.materiales.iter();
let mut mano_obra_iter = task.mano_obra.iter();
let mut costos_indirectos_iter = task.costos_indirectos.iter();
let costo_total_tarea = task.get_total_materiales() +
task.get_total_mano_obra() +
task.get_total_costo_indirectos();
let task_rows = task.get_max_row() + 1;
let mut rows = Vec::new();
for i2 in 0..task_rows {
let mut row = Vec::new();
if i2 == 0 {
if i1 == 0{
row.push(TableCell::TableData {
content: self.nombre.clone(),
rowspan: Some(total_rows),
colspan: None
});
}
row.push(TableCell::TableData {
content: task.nombre.clone(),
rowspan: Some(task_rows),
colspan: None
});
row.push(TableCell::TableData {
content: task.dur.to_string(),
rowspan: Some(task_rows),
colspan: None
});
}
macro_rules! add_section {
($iter:expr, $total:expr) => {{
if let Some(costo) = $iter.next() {
row.push(TableCell::TableData {
content: costo.cantidad.to_string(),
rowspan: None,
colspan: None
});
row.push(TableCell::TableData {
content: costo.producto.clone(),
rowspan: None,
colspan: None
});
row.push(TableCell::TableData {
content: format!("{:.2}", costo.precio_unitario),
rowspan: None,
colspan: None
});
row.push(TableCell::TableData {
content: format!("{:.2}", costo.get_total()),
rowspan: None,
colspan: None
});
} else if i2 == task.get_max_row() {
row.push(TableCell::EmptyCell {rowspan: None, colspan: Some(3)});
row.push(TableCell::TableData {
content: format!("{:.2}", $total),
rowspan: None,
colspan: None
});
} else {
for _ in 0..4 {
row.push(TableCell::EmptyCell {rowspan: None, colspan: None});
}
}
}}
}
add_section!(materiales_iter, task.get_total_materiales());
add_section!(mano_obra_iter, task.get_total_mano_obra());
add_section!(costos_indirectos_iter, task.get_total_costo_indirectos());
if i2 == 0 {
row.push(TableCell::TableData {
content: format!("{:.2}", costo_total_tarea),
rowspan: Some(task_rows),
colspan: None
});
}
rows.push(row);
}
rows.into_iter()
}).collect::<Vec<_>>()
}
}
struct CostoActividad(Vec<Actividad>);
impl CostoActividad {
fn add_costo_indirecto_from_builders(&mut self, builders: &[Rc<Fn(u32, f64, f64, f64) -> Costo>]) {
for actividad in &mut self.0 {
actividad.add_costo_indirecto_from_builders(builders);
}
}
fn get_presupuesto(&self) -> Option<Presupuesto> {
self.0.iter().map(|act| act.get_presupuesto()).fold(None, |p1, p2| {
match (p1, p2) {
(Some(p1), Some(p2)) => Some(p1.merge(p2)),
(Some(p1), None) => Some(p1),
(None, Some(p2)) => Some(p2),
_ => None
}
})
}
fn as_html_table(&self) -> Table {
let mut dur_total = 0;
let mut total_materiales = 0.0;
let mut total_mano_obra = 0.0;
let mut total_costos_indirectos = 0.0;
let mut rows = vec![
vec![
TableCell::EmptyCell {rowspan: Some(2), colspan: Some(2)},
TableCell::TableHeader {content: "Duración (días)".to_string(), rowspan: Some(2), colspan: None},
TableCell::TableHeader {content: "Materiales directos".to_string(), rowspan: None, colspan: Some(4)},
TableCell::TableHeader {content: "Mano de obra directa".to_string(), rowspan: None, colspan: Some(4)},
TableCell::TableHeader {content: "Costos indirectos".to_string(), rowspan: None, colspan: Some(4)},
TableCell::TableHeader {content: "Costo total por actividad".to_string(), rowspan: Some(2), colspan: None}
],
vec![
TableCell::TableHeader {content: "Cantidad".to_string(), rowspan: None, colspan: None},
TableCell::TableHeader {content: "Producto".to_string(), rowspan: None, colspan: None},
TableCell::TableHeader {content: "Costo Unitario".to_string(), rowspan: None, colspan: None},
TableCell::TableHeader {content: "Total".to_string(), rowspan: None, colspan: None},
TableCell::TableHeader {content: "Cantidad".to_string(), rowspan: None, colspan: None},
TableCell::TableHeader {content: "Producto".to_string(), rowspan: None, colspan: None},
TableCell::TableHeader {content: "Costo Unitario".to_string(), rowspan: None, colspan: None},
TableCell::TableHeader {content: "Total".to_string(), rowspan: None, colspan: None},
TableCell::TableHeader {content: "Cantidad".to_string(), rowspan: None, colspan: None},
TableCell::TableHeader {content: "Producto".to_string(), rowspan: None, colspan: None},
TableCell::TableHeader {content: "Costo Unitario".to_string(), rowspan: None, colspan: None},
TableCell::TableHeader {content: "Total".to_string(), rowspan: None, colspan: None},
]
];
for actividad in &self.0 {
dur_total += actividad.get_dur_total();
total_materiales += actividad.get_total_materiales();
total_mano_obra += actividad.get_total_mano_obra();
total_costos_indirectos += actividad.get_total_costo_indirectos();
rows = rows.into_iter().chain(actividad.get_rows().into_iter()).collect::<Vec<_>>();
}
let total_neto = total_materiales + total_mano_obra + total_costos_indirectos;
let table_body = rows.into_iter().chain(vec![vec![
TableCell::EmptyCell {rowspan: None, colspan: Some(2)},
TableCell::TableData {content: dur_total.to_string(), rowspan: None, colspan: None},
TableCell::TableData {content: "Total de Materiales".to_string(), rowspan: None, colspan: Some(3)},
TableCell::TableData {content: format!("{:.2}", total_materiales), rowspan: None, colspan: None},
TableCell::TableData {content: "Total de Mano de Obra directa".to_string(), rowspan: None, colspan: Some(3)},
TableCell::TableData {content: format!("{:.2}", total_mano_obra), rowspan: None, colspan: None},
TableCell::TableData {content: "Total de Costos Indirectos".to_string(), rowspan: None, colspan: Some(3)},
TableCell::TableData {content: format!("{:.2}", total_costos_indirectos), rowspan: None, colspan: None},
TableCell::TableData {content: format!("{:.2}", total_neto), rowspan: None, colspan: None}
]].into_iter()).collect::<Vec<_>>();
Table(table_body)
}
}
struct Presupuesto(HashMap<u8, HashMap<String, (u32, f64, f64)>>);
impl Presupuesto {
fn material() -> u8 { 1 }
fn mano_obra() -> u8 { 2 }
fn costo_indirecto() -> u8 { 3 }
fn new() -> Presupuesto {
Presupuesto(HashMap::new())
}
fn add_costo(&mut self, section: u8, costo: &Costo) {
if self.0.contains_key(&section) {
let inner_map = self.0.get_mut(&section).unwrap();
if inner_map.contains_key(&costo.producto) {
let &mut (ref mut cantidad, _, ref mut total) = inner_map.get_mut(&costo.producto).unwrap();
*cantidad = cmp::max(*cantidad, costo.cantidad);
*total += costo.get_total();
} else {
inner_map.insert(costo.producto.clone(), (costo.cantidad, costo.precio_unitario, costo.get_total()));
}
} else {
let mut new_map = HashMap::new();
new_map.insert(costo.producto.clone(), (costo.cantidad, costo.precio_unitario, costo.get_total()));
self.0.insert(section, new_map);
}
}
fn merge(mut self, other: Presupuesto) -> Presupuesto {
for (key, other_inner_map) in other.0.iter() {
if self.0.contains_key(key) {
let self_inner_map = self.0.get_mut(key).unwrap();
for (product, &(c1, precio_unitario, t1)) in other_inner_map.iter() {
if self_inner_map.contains_key(product) {
let &mut (ref mut c2, _, ref mut t2) = self_inner_map.get_mut(product).unwrap();
*c2 = cmp::max(*c2, c1);
*t2 += t1;
} else {
self_inner_map.insert(product.clone(), (c1, precio_unitario, t1));
}
}
} else {
self.0.insert(*key, other_inner_map.clone());
}
}
self
}
fn as_html_table(&self) -> Table {
let mut total_materiales = 0.0;
let mut total_mano_obra = 0.0;
let mut total_costos_indirectos = 0.0;
let mut rows = vec![vec![
TableCell::TableHeader {content: "Cantidad".to_string(), rowspan: None, colspan: None},
TableCell::TableHeader {content: "Productos".to_string(), rowspan: None, colspan: None},
TableCell::TableHeader {content: "Costo Unitario".to_string(), rowspan: None, colspan: None},
TableCell::TableHeader {content: "Total".to_string(), rowspan: None, colspan: None},
]];
macro_rules! add_table_section_rows {
($key:expr, $counter:ident) => {{
if let Some(map) = self.0.get(&$key) {
$counter += map
.iter()
.map(|(_, &(_, _, total))| total)
.sum();
rows = rows.into_iter().chain(map
.iter()
.map(|(producto, &(cantidad, precio_unitario, total))| {
vec![
TableCell::TableData {content: cantidad.to_string(), rowspan: None, colspan: None},
TableCell::TableData {content: producto.clone(), rowspan: None, colspan: None},
TableCell::TableData {content: format!("{:.2}", precio_unitario), rowspan: None, colspan: None},
TableCell::TableData {content: format!("{:.2}", total), rowspan: None, colspan: None}
]
}
)).collect::<Vec<_>>();
}
}}
}
add_table_section_rows!(Presupuesto::material(), total_materiales);
rows.push(vec![
TableCell::TableData {content: "Total de Materiales".to_string(), rowspan: None, colspan: Some(3)},
TableCell::TableData {content: format!("{:.2}", total_materiales), rowspan: None, colspan: None},
]);
add_table_section_rows!(Presupuesto::mano_obra(), total_mano_obra);
rows.push(vec![
TableCell::TableData {content: "Total de Mano de Obra".to_string(), rowspan: None, colspan: Some(3)},
TableCell::TableData {content: format!("{:.2}", total_mano_obra), rowspan: None, colspan: None},
]);
add_table_section_rows!(Presupuesto::costo_indirecto(), total_costos_indirectos);
rows.push(vec![
TableCell::TableData {content: "Total de Costos Indirectos".to_string(), rowspan: None, colspan: Some(3)},
TableCell::TableData {content: format!("{:.2}", total_costos_indirectos), rowspan: None, colspan: None},
]);
let total_costos = total_materiales + total_mano_obra + total_costos_indirectos;
rows.push(vec![
TableCell::TableData {content: "Total de Costos".to_string(), rowspan: None, colspan: Some(3)},
TableCell::TableData {content: format!("{:.2}", total_costos), rowspan: None, colspan: None},
]);
Table(rows)
}
}
fn create_builder_mano_obra(puesto: &'static str, cantidad: u32, salario_base: f64) ->
Rc<Fn(u32, f64, f64, f64) -> Costo>
{
Rc::new(move |dur, _, _, _| Costo {
cantidad: cantidad,
producto: puesto.to_string(),
precio_unitario: salario_base / 30.0 * dur as f64
})
}
fn main() {
const TASA_CAMBIO_DOLAR: f64 = 28.66;
//Materiales
let m1 = Costo {
producto: "LibreOffice".to_string(),
cantidad: 4,
precio_unitario: 0.0
};
let m2 = Costo {
producto: "Arch Linux".to_string(),
cantidad: 4,
precio_unitario: 0.0
};
let m3 = Costo {
producto: "StarUML 2".to_string(),
cantidad: 4,
precio_unitario: 0.0
};
let m4 = Costo {
producto: "Android Studio".to_string(),
cantidad: 4,
precio_unitario: 0.0
};
let m5 = Costo {
producto: "Visual Studio Code".to_string(),
cantidad: 4,
precio_unitario: 0.0
};
let m6 = Costo {
producto: "Phoenix Framework".to_string(),
cantidad: 8,
precio_unitario: 0.0
};
let m7 = Costo {
producto: "Licencia de Google Play Store".to_string(),
cantidad: 1,
precio_unitario: 25.0 * TASA_CAMBIO_DOLAR
};
let m8 = Costo {
producto: "Licencia de la App Store".to_string(),
cantidad: 1,
precio_unitario: 99.0 * TASA_CAMBIO_DOLAR
};
let m9 = Costo {
producto: "Paquete de instancias de AWS EC2 Linux t2.medium + Disco Duros".to_string(),
cantidad: 1,
precio_unitario: 153.13 * TASA_CAMBIO_DOLAR
};
let m10 = Costo {
producto: "Paquete de instancias de AWS RDS t2.medium".to_string(),
cantidad: 1,
precio_unitario: 100.72 * TASA_CAMBIO_DOLAR
};
//Mano de obra
let analista = create_builder_mano_obra("Analista de Sistemas", 1, 12500.0);
let programador_1 = create_builder_mano_obra("Programador", 1, 10000.0);
let programador_2 = create_builder_mano_obra("Programador", 2, 10000.0);
let dba = create_builder_mano_obra("Administrador de Base de Datos", 1, 10000.0);
//Costos indirectos
let costo_papel = Costo {
producto: "Papelería".to_string(),
cantidad: 1,
precio_unitario: 50.0
};
let costo_transporte = Rc::new(move |dur, _, _, _| Costo {
cantidad: dur,
producto: "Transporte de mano de obra".to_string(),
precio_unitario: 150.0
});
let costo_electricidad = Rc::new(move |dur, _, _, _| Costo {
cantidad: 1,
producto: "Luz eléctrica".to_string(),
precio_unitario: 2.4 * 8.0 * dur as f64
});
let costo_internet_builder = |cantidad| Rc::new(move |_, _, _, _| Costo {
cantidad: cantidad,
producto: "Internet".to_string(),
precio_unitario: 550.0
});
let costo_dep_pc = |cantidad| Rc::new(move |dur, _, _, _| Costo {
cantidad: cantidad,
producto: "Depreciación de computadoras".to_string(),
precio_unitario: [22.91, 58.33, 31.25, 14.5]
.iter()
.map(|pd| pd * TASA_CAMBIO_DOLAR)
.sum::<f64>() / 30.0 * dur as f64 / 4.0 /*4 pcs*/
});
let costo_impuestos_prof = Rc::new(move |_, _, mano_obra, _| Costo {
cantidad: 1,
producto: "Impuestos por servicios profesionales".to_string(),
precio_unitario: mano_obra * 0.1
});
//Actividad 1
let mut t1_1 = Tarea::new("Inpección de la infraestructuara del MTI".to_string(), 3);
let mut t1_2 = Tarea::new("Recolección de requerimientos del negocio".to_string(), 10);
let mut t1_3 = Tarea::new("Elaboración de presupuesto y contrato".to_string(), 10);
let mut t1_4 = Tarea::new("Elaboración del concepto del sistema".to_string(), 5);
let mut t1_5 = Tarea::new("Elaboración del plan de gestión de riesgos".to_string(), 2);
t1_1.add_costo_indirecto(costo_papel.clone());
t1_1.add_materiales(m1);
t1_1.add_materiales(m2);
t1_1.add_costo_indirecto_from_builders(&[costo_transporte.clone()]);
t1_2.add_costo_indirecto(costo_papel.clone());
t1_2.add_costo_indirecto_from_builders(&[costo_transporte.clone()]);
t1_3.add_costo_indirecto(costo_papel.clone());
t1_3.add_costo_indirecto_from_builders(&[costo_electricidad.clone()]);
t1_4.add_costo_indirecto_from_builders(&[costo_electricidad.clone()]);
t1_5.add_costo_indirecto_from_builders(&[costo_electricidad.clone()]);
let mut t1 = Actividad {
nombre: "Actividad 1: Concepción".to_string(),
tareas: vec![t1_1, t1_2, t1_3, t1_4, t1_5]
};
t1.add_costo_indirecto_from_builders(&[costo_dep_pc(1), costo_internet_builder(1)]);
t1.add_mano_obra_from_builders(&[analista.clone()]);
//Actividad 2
let mut t2_1 = Tarea::new("Análisis de requerimientos del sistema".to_string(), 5);
let t2_2 = Tarea::new("Elaboración de casos de uso".to_string(), 3);
let t2_3 = Tarea::new("Diseño de componentes a nivel arquitectónico".to_string(), 7);
let t2_4 = Tarea::new("Elaboración del plan de pruebas".to_string(), 2);
let t2_5 = Tarea::new("Especificación del sistema".to_string(), 13);
let t2_6 = Tarea::new("Iteración II".to_string(), 15);
t2_1.add_materiales(m3);
let mut t2 = Actividad {
nombre: "Actividad 2: Elaboración".to_string(),
tareas: vec![t2_1, t2_2, t2_3, t2_4, t2_5, t2_6]
};
t2.add_costo_indirecto_from_builders(&[
costo_electricidad.clone(),
costo_dep_pc(2),
costo_internet_builder(2)
]);
t2.add_mano_obra_from_builders(&[analista.clone(), programador_1.clone()]);
//Actividad 3
let mut t3_1 = Tarea::new("Construcción de componentes individuales".to_string(), 30);
let mut t3_2 = Tarea::new("Integración de componentes".to_string(), 15);
let mut t3_3 = Tarea::new("Ejecución del plan de pruebas".to_string(), 45);
let mut t3_4 = Tarea::new("Iteración II".to_string(), 25);
let mut t3_5 = Tarea::new("Iteración III".to_string(), 20);
t3_1.add_materiales(m4);
t3_1.add_materiales(m5);
t3_1.add_materiales(m6);
t3_1.add_materiales(m7);
t3_1.add_materiales(m8);
t3_1.add_materiales(m9);
t3_1.add_materiales(m10);
t3_1.add_mano_obra_from_builders(&[programador_2.clone()]);
t3_1.add_costo_indirecto_from_builders(&[costo_internet_builder(2), costo_dep_pc(2)]);
t3_2.add_mano_obra_from_builders(&[programador_2.clone()]);
t3_2.add_costo_indirecto_from_builders(&[costo_internet_builder(2), costo_dep_pc(2)]);
t3_3.add_mano_obra_from_builders(&[analista.clone(), dba.clone()]);
t3_3.add_costo_indirecto_from_builders(&[costo_internet_builder(2), costo_dep_pc(2)]);
t3_4.add_mano_obra_from_builders(&[
programador_2.clone(),
analista.clone(),
dba.clone()
]);
t3_4.add_costo_indirecto_from_builders(&[costo_internet_builder(4), costo_dep_pc(4)]);
t3_5.add_mano_obra_from_builders(&[
programador_2.clone(),
analista.clone(),
dba.clone()
]);
t3_5.add_costo_indirecto_from_builders(&[costo_internet_builder(4), costo_dep_pc(4)]);
let mut t3 = Actividad {
nombre: "Actividad 3: Construcción".to_string(),
tareas: vec![t3_1, t3_2, t3_3, t3_4, t3_5]
};
t3.add_costo_indirecto_from_builders(&[costo_electricidad.clone()]);
//Actividad 4
let t4_1 = Tarea::new("Migración de componentes al entorno de producción".to_string(), 7);
let t4_2 = Tarea::new("Verificación de funcionalidad en producción".to_string(), 15);
let t4_3 = Tarea::new("Evaluar retroalimentación del usuario".to_string(), 8);
let t4_4 = Tarea::new("Iteración II".to_string(), 20);
let mut t4 = Actividad {
nombre: "Actividad 4: Ejecución".to_string(),
tareas: vec![t4_1, t4_2, t4_3, t4_4]
};
t4.add_costo_indirecto_from_builders(&[
costo_electricidad.clone(),
costo_dep_pc(2),
costo_internet_builder(2)
]);
t4.add_mano_obra_from_builders(&[analista, dba]);
let mut costo_actividad = CostoActividad(vec![t1, t2, t3, t4]);
costo_actividad.add_costo_indirecto_from_builders(&[costo_impuestos_prof]);
let html = Html(vec![
costo_actividad.as_html_table(),
costo_actividad.get_presupuesto().unwrap().as_html_table()
]);
html.save_to("output.html").unwrap();
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment