Option Explicit
'algunas inicializaciones están en el main


'VARIABLES Y CTES GLOBALES


'modificación 1/2 tras entrega proyecto:
'Global Const Directorio = "c:\ccne\"
Global Directorio
'fin modificación 1/2
Global Const Extensión = ".txt"


'Archivo de ayuda
Global Const NombreArchAyuda = "ccne_ayd"
Global ArchAyuda As String'=Directorio+NombreArchAyuda+Extensión


'Archivo lista de comp neu:

Global Const NombreArchLista = "ccne_lst"
Global ArchLista As String'=Directorio+NombreArchLista+Extensión

Global TiempoDeAntelación As Integer
Global NúmCompNeu As Integer

Type TipoListaCompNeu
    Etiqueta As String
    Modelo As Integer'cte
    LastComentarioFijo As Integer'cte
    PróxMes As Integer
    PróxAño As Integer
End Type
Global ListaCompNeu() As TipoListaCompNeu


'comp neu seleccionado (apuntado)

Global CompApuntado As Integer
Global Subdirectorio As String'=Directorio+trim$(str$(CompApuntado))+"\"


'Datos y estado (lo básico de la última calibración) del comp neu:

Global Const NombreArchCompNeu = "comp_neu"
Global ArchCompNeu As String'=Subdirectorio+NombreArchCompNeu+Extensión

Type TipoCompNeu
    Etiqueta As String
    Modelo As Integer'cte
    Fórmula As String'versión neumática
    Diámetro As Single'en micras
    Apreciación As Single'micras
    TipoCalibre As Integer'cte
    Localización As String
    Responsable As String
    NúmCalibraciones As Integer
    LastIncertidumbre As Single'micras
	'ojo que es I, no U como en los pat cil y reloj
    LastFactork As Single'micras
    LastComentarioFijo As Integer'cte
    PróxMes As Integer
    PróxAño As Integer
End Type
Global CompNeu As TipoCompNeu


'Archivo de estado del reloj centesimal

Global Const NombreArchReloj = "Reloj"
Global ArchReloj As String'=Subdirectorio+NombreArchReloj+Extensión

Type TipoReloj
    NúmCalibraciones As Integer
    LastIncertidumbre As Single
    LastComentarioFijo As Integer'cte
    PróxMes As Integer
    PróxAño As Integer
End Type
Global reloj As TipoReloj


'Archivo de datos y estado de los patrones

Global Const NombreArchPatCil = "pat_cil"
Global ArchPatCil As String'=Subdirectorio+NombreArchPatCil+Extensión

Global LocalizaciónPatCil As String
Global ResponsablePatCil As String
Global NúmPatCil As Integer

Type TipoPatCil
    Etiqueta As String
    DiámetroNominal As Single'micras
    Recomendación As Integer'cte
    NúmCalibraciones As Integer
    LastCorrección As Integer'cte
    LastDiámetro As Single'micras
    LastIncertidumbre As Single'micras
    LastComentarioFijo As Integer'cte
    PróxMes As Integer
    PróxAño As Integer
End Type
Global PatCil() As TipoPatCil

Global PatCilApuntado As Integer



'ARCHIVOS DE CALIBRACIÓN


'Archivo de calibración de cada pat cil

Type TipoCalPatCil
    día As Integer
    Mes As Integer
    año As Integer
    DiámetroActual As Single'micras
    IdMedidora As String
    IncertidumbreMedidora As Single'micras; es I
    FactorkMedidora As Single
    TipoErrorDeDesviación As Integer'cte
    FactorMultiplicador As Single
    IncertidumbreEsfera As Single'micras; es I
    FactorkEsfera As Single
    PuntosPalpadoEsfera As Integer
    ErrorPalpadores As Single'micras o micras cuadradas, según TipoErrorDeDesviación
    PuntosPalpadoPatCil As Integer
    DiámetroMedio As Single
    ErrorDiámetro As Single'en realidad, es en el radio
    Corrección As Integer'cte, sí o no
    DiámetroFinal As Single
    Incertidumbre As Single
    ComentarioFijo As Integer'cte
    ComentarioLargo As String
    PróxMes As Integer
    PróxAño As Integer
    Encargado As String
    Supervisor As String
End Type
Global CalPatCil As TipoCalPatCil


'para el reloj centesimal:

Type TipoCalReloj
    día As Integer
    Mes As Integer
    año As Integer
    IdBloquesPatrón As String
    IdPatrónPlanitud As String
    NúmBloquesPatrón As Integer
    IncertidumbrePatrones As Single'micras; es I
    FactorkPatrones As Single
    Incertidumbre As Single'micras
    ComentarioFijo As Integer'cte
    ComentarioLargo As String
    PróxMes As Integer
    PróxAño As Integer
    Encargado As String
    Supervisor As String
End Type
Global CalReloj As TipoCalReloj

Global BloquesPatrón() As Single


'para el comp neu

Type TipoCalCompNeu
    día As Integer
    Mes As Integer
    año As Integer
    NúmCalReloj As Integer
    IncertidumbreReloj As Single
    NúmPatCil As Integer
    Incertidumbre As Single'micras; ojo que es I
    Factork As Single
    ComentarioFijo As Integer'cte
    ComentarioLargo As String
    PróxMes As Integer
    PróxAño As Integer
    Encargado As String
    Supervisor As String
End Type
Global CalCompNeu As TipoCalCompNeu

Type TipoPatCilCal
    Etiqueta As String
    NúmCal As Integer
    Diámetro As Single
    Incertidumbre As Single
End Type
Global PatCilCal() As TipoPatCilCal


'globales para reloj y comp neu:

Global NúmSaltos As Integer
    'comp neu: CalCompNeu.NúmPatCilCal - 1
    'reloj:  CalReloj.NúmBloquesPatrón - 1
Global NúmVecesPorSalto As Integer
'valores para Referencia y MatrizSaltos, definidos aquí porque se necesitan ya
Global Const creciente = True'-1
Global Const decreciente = False'0
Global Referencia(creciente To decreciente) As Single
    'valores de referencia de la escala, donde empieza el salto
Global MatrizSaltos() As Single'de estructura:
'MatrizSaltos (sentido, nº del salto, nº vez que se mide y resultados)
'para sentido:
    'creciente a decreciente
'para nº del salto (salto):
    'de 1 a NúmSaltos
'para nº vez que se mide y resultados (vez)
    '0: ValorNominal
    '1 a NúmVecesPorSalto: Valores que se cogen
    'NúmVecesPorSalto+1: ValorMedioMedidas
    'NúmVecesPorSalto+2: s_salto
    'NúmVecesPorSalto+3: U_salto
Global Const ValorNominal = 0
Global ValorMedioMedidas As Integer'=NúmVecesPorSalto+1
Global s_salto As Integer'=NúmVecesPorSalto+2
Global U_salto As Integer'=NúmVecesPorSalto+3



'CTES EMPLEADAS EN LOS VALORES ANTERIORES


'Valores para el tipo de 'Modelo' de comp neu
Global Const C60 = 0
Global Const Estándar = 1
Global Const Universal = 2
Global ModeloTexto(0 To 2) As String

'Valores para 'ComentarioFijo' de la calibración, y para clasificar la lista
Global Const CalBuena = 5
Global Const CalCaducaPronto = 4
Global Const CalCaducaYa = 3
Global Const CalCaducada = 2
Global Const CalMala = 1
Global Const CalCero = 0

'TipoCalibre (de medida, el pat cil es el otro)
Global Const Tampón = True
Global Const Anillo = False

'ítems para la lista de errores de desviación: TipoErrorDeDesviación
Global Const DesviaciónMedia = 0
Global Const DesviaciónTípica = 1
Global Const DesviaciónTípicaNmenos1 = 2
Global Const DesviaciónTípicaMedia = 3
Global Const DiferenciaDeRadiosExtremos = 4
Global Const varianza = 5
Global Const VarianzaNmenos1 = 6
Global Const VarianzaTípicaMedia = 7
Global ErrorDesviaciónTexto(0 To 7) As String


'VALORES VARIOS:


'nombres de los meses
Global Mes(1 To 12) As String

Global Const micra = " µm"
Global NuevaLínea As String * 1

'flechas para el ratón
Global Const Def = 0, RelojArena = 11

'ctes para el NombrePatCil: Mayúsculas, minúsculas, singular y plural
Global Const CalibreMedida = -1'el órgano de medida
Global Const Minus1 = 0
Global Const Mayusc1 = 1
Global Const Minus2 = 2
Global Const Mayusc2 = 3

'para la función RecogidaDeMedidas
Global Const Paraelcompneu = True
Global Const Paraelreloj = False

'para el nº de calibración en la consulta
Global ConsultaNúmCal As String

'texto antes de una calibración (los espacios quedan anárquicos)
Global Const CondicionesDeCalibración1 = " Verificaciones previas: Previamente a la calibración debe realizarse una inspección visual de todos los elementos participantes, comprobando su buen estado, limpieza, escalas, partes móviles, sistemas de fijación, etc."
Global Const CondicionesDeCalibración2 = " Temperatura: La calibración debe realizarse en un laboratorio de metrología de ambiente controlado, siendo la temperatura de '20 ºC' con una máxima desviación de '± 1 ºC'."
Global Const CondicionesDeCalibración3 = " Condiciones ambientales de calibración: Si no lo están ya, cada elemento implicado en la calibración debe permanecer durante un tiempo en reposo, adaptación y estabilización en las condiciones ambientales a las que se someta. Para evitar el calentamiento durante la manipulación, es recomendable emplear guantes."

'actualiza los valores de la lista
'útil después de calibrar un comp neu, o introducir uno nuevo
'ojo que no graba nada, eso se hace al salir o al introducir el nuevo
Sub ActualizarValoresLista ()

    ListaCompNeu(CompApuntado).Etiqueta = CompNeu.Etiqueta
    ListaCompNeu(CompApuntado).Modelo = CompNeu.Modelo
    ListaCompNeu(CompApuntado).LastComentarioFijo = CompNeu.LastComentarioFijo
    ListaCompNeu(CompApuntado).PróxMes = CompNeu.PróxMes
    ListaCompNeu(CompApuntado).PróxAño = CompNeu.PróxAño

End Sub

Sub ArchCompNeu_Leer ()

    screen.MousePointer = RelojArena

    Open ArchCompNeu For Input As #1
	Input #1, CompNeu.Etiqueta
	Input #1, CompNeu.Modelo
	Input #1, CompNeu.Fórmula
	Input #1, CompNeu.Diámetro
	Input #1, CompNeu.Apreciación
	Input #1, CompNeu.TipoCalibre
	Input #1, CompNeu.Localización
	Input #1, CompNeu.Responsable
	Input #1, CompNeu.NúmCalibraciones
	Input #1, CompNeu.LastIncertidumbre
	Input #1, CompNeu.LastFactork
	Input #1, CompNeu.LastComentarioFijo
	Input #1, CompNeu.PróxMes
	Input #1, CompNeu.PróxAño
    Close #1
    
    screen.MousePointer = Def

End Sub

Sub ArchCompNeu_Salvar ()

    screen.MousePointer = RelojArena

    Open ArchCompNeu For Output As #1
	Write #1, CompNeu.Etiqueta
	Write #1, CompNeu.Modelo
	Write #1, CompNeu.Fórmula
	Write #1, CompNeu.Diámetro
	Write #1, CompNeu.Apreciación
	Write #1, CompNeu.TipoCalibre
	Write #1, CompNeu.Localización
	Write #1, CompNeu.Responsable
	Write #1, CompNeu.NúmCalibraciones
	Write #1, CompNeu.LastIncertidumbre
	Write #1, CompNeu.LastFactork
	Write #1, CompNeu.LastComentarioFijo
	Write #1, CompNeu.PróxMes
	Write #1, CompNeu.PróxAño
    Close #1

    screen.MousePointer = Def

End Sub

Sub ArchLista_Leer ()
    Dim i As Integer
    
    screen.MousePointer = RelojArena

    On Error GoTo ErrorArchLista

    Open ArchLista For Input As #1

    Input #1, TiempoDeAntelación
    Input #1, NúmCompNeu
	
    ReDim ListaCompNeu(1 To NúmCompNeu + 1)
    'el '+1' es para que haya un espacio para añadir un nuevo elemento,
    'y para cuando NúmCompNeu=0

    For i = 1 To NúmCompNeu
	Input #1, ListaCompNeu(i).Etiqueta
	Input #1, ListaCompNeu(i).Modelo
	Input #1, ListaCompNeu(i).LastComentarioFijo
	Input #1, ListaCompNeu(i).PróxMes
	Input #1, ListaCompNeu(i).PróxAño
    Next i

    Close #1

    screen.MousePointer = Def

Exit Sub

ErrorArchLista:
    'significa que no hay el archivo, así que se cogen los valores por defecto
    TiempoDeAntelación = 1
    NúmCompNeu = 0
    ReDim ListaCompNeu(1 To NúmCompNeu + 1)'para poder meter uno nuevo
    screen.MousePointer = Def
    Close #1'creo que no es necesario, pero creo que no está de más ponerlo
Exit Sub
    
End Sub

Sub ArchLista_Salvar ()
    Dim i As Integer
    
    screen.MousePointer = RelojArena

    Open ArchLista For Output As #1

    Write #1, TiempoDeAntelación
    Write #1, NúmCompNeu

    For i = 1 To NúmCompNeu
	Write #1, ListaCompNeu(i).Etiqueta
	Write #1, ListaCompNeu(i).Modelo
	Write #1, ListaCompNeu(i).LastComentarioFijo
	Write #1, ListaCompNeu(i).PróxMes
	Write #1, ListaCompNeu(i).PróxAño
    Next i

    Close #1
    
    screen.MousePointer = Def

End Sub

Sub ArchPatCil_Leer ()

    Dim i As Integer

    screen.MousePointer = RelojArena

    Open ArchPatCil For Input As #1
    
    Input #1, LocalizaciónPatCil
    Input #1, ResponsablePatCil
    Input #1, NúmPatCil

    ReDim PatCil(1 To NúmPatCil + 1)

    For i = 1 To NúmPatCil
	Input #1, PatCil(i).Etiqueta
	Input #1, PatCil(i).DiámetroNominal
	Input #1, PatCil(i).Recomendación
	Input #1, PatCil(i).NúmCalibraciones
	Input #1, PatCil(i).LastCorrección
	Input #1, PatCil(i).LastDiámetro
	Input #1, PatCil(i).LastIncertidumbre
	Input #1, PatCil(i).LastComentarioFijo
	Input #1, PatCil(i).PróxMes
	Input #1, PatCil(i).PróxAño
    Next i

    Close #1

    screen.MousePointer = Def

End Sub

Sub ArchPatCil_Salvar ()

    Dim i As Integer

    screen.MousePointer = RelojArena

    Open ArchPatCil For Output As #1
    
    Write #1, LocalizaciónPatCil
    Write #1, ResponsablePatCil
    Write #1, NúmPatCil

    For i = 1 To NúmPatCil
	Write #1, PatCil(i).Etiqueta
	Write #1, PatCil(i).DiámetroNominal
	Write #1, PatCil(i).Recomendación
	Write #1, PatCil(i).NúmCalibraciones
	Write #1, PatCil(i).LastCorrección
	Write #1, PatCil(i).LastDiámetro
	Write #1, PatCil(i).LastIncertidumbre
	Write #1, PatCil(i).LastComentarioFijo
	Write #1, PatCil(i).PróxMes
	Write #1, PatCil(i).PróxAño
    Next i

    Close #1

    screen.MousePointer = Def

End Sub

Sub ArchReloj_Leer ()

    screen.MousePointer = RelojArena

    Open ArchReloj For Input As #1
	Input #1, reloj.NúmCalibraciones
	Input #1, reloj.LastIncertidumbre
	Input #1, reloj.LastComentarioFijo
	Input #1, reloj.PróxMes
	Input #1, reloj.PróxAño
    Close #1
    
    screen.MousePointer = Def

End Sub

Sub ArchReloj_Salvar ()

    screen.MousePointer = RelojArena

    Open ArchReloj For Output As #1
	Write #1, reloj.NúmCalibraciones
	Write #1, reloj.LastIncertidumbre
	Write #1, reloj.LastComentarioFijo
	Write #1, reloj.PróxMes
	Write #1, reloj.PróxAño
    Close #1
    
    screen.MousePointer = Def

End Sub

'actualiza el nº de meses
Sub CambioMarcoPróxCal (vent As Form)
    Dim tiempo As Integer
    tiempo = DifDeFechas(1 + vent.ListaPróxMes.ListIndex, Year(Now) + vent.ListaPróxAño.ListIndex)
    vent.MarcoPróxCal.Caption = "Próxima calibración (" + FunciónDecimal(tiempo) + " mes" + Plural(tiempo) + "):"
End Sub

Sub CentrarVentana (v As Form)
    v.Move (screen.Width - v.Width) / 2, (screen.Height - v.Height) / 2
End Sub

'los valores a dar son:
    'PróxMes, PróxAño
    'Encargado, Supervisor
    'ComentarioFijo, ComentarioLargo
    'DíaActual, MesActual, AñoActual
    'Vent
'devuelve true si todo está bien, false si no
Function ComprobarValoresComunesResultadoCal (PróxMes As Integer, PróxAño As Integer, Encargado As String, Supervisor As String, ComentarioFijo As Integer, ComentarioLargo As String, DíaActual As Integer, MesActual As Integer, AñoActual As Integer, vent As Form) As Integer

    PróxMes = vent.ListaPróxMes.ListIndex + 1
    PróxAño = vent.ListaPróxAño.ListIndex + Year(Now)
    If DifDeFechas(PróxMes, PróxAño) < 0 Then
	MsgBox "La fecha de próxima calibración es posterior a la fecha actual", 16, "Aviso"
	vent.ListaPróxMes.SetFocus
	ComprobarValoresComunesResultadoCal = False
	Exit Function
    End If

    Encargado = Trim$(vent.BoxEncargado.Text)
    If Len(Encargado) = 0 Then
	MsgBox "No hay identificación del encargado que ha realizado la calibración", 16, "Aviso"
	vent.BoxEncargado.SetFocus
	ComprobarValoresComunesResultadoCal = False
	Exit Function
    End If

    Supervisor = Trim$(vent.BoxSupervisor.Text)
    If Len(Supervisor) = 0 Then
	MsgBox "No hay identificación del supervisor de la calibración", 16, "Aviso"
	vent.BoxSupervisor.SetFocus
	ComprobarValoresComunesResultadoCal = False
	Exit Function
    End If

    ComentarioFijo = IIf(vent.OpciónResultadoAceptable.Value = True, CalBuena, CalMala)
    ComentarioLargo = Trim$(vent.BoxComentarioLargo.Text)

    DíaActual = Day(Now)
    MesActual = Month(Now)
    AñoActual = Year(Now)


    ComprobarValoresComunesResultadoCal = True
    
End Function

'pone los nombres a los archivos del comp neu apuntado
'debe antes establecerse el Subdirectorio
Sub DefNombresArch ()

    ArchCompNeu = Subdirectorio + NombreArchCompNeu + Extensión
    ArchReloj = Subdirectorio + NombreArchReloj + Extensión
    ArchPatCil = Subdirectorio + NombreArchPatCil + Extensión

End Sub

'devuelve la dif, en meses, entre la fecha dada y la actual
Function DifDeFechas (MesMes As Integer, AñoAño As Integer) As Integer
    DifDeFechas = (MesMes - Month(Now) + 12 * (AñoAño - Year(Now)))
End Function

'devuelve una cadena con la fecha indicada
Function Fecha (día As Integer, NúmMes As Integer, año As Integer) As String
    Fecha = FunciónDecimal(día) + " de " + Mes(NúmMes) + " de" + Str$(año)
End Function

'devuelve una cadena con la fecha actual
Function FechaActual () As String
    FechaActual = Fecha(Day(Now), Month(Now), Year(Now))
End Function

'devuelve una cadena con la fecha de calibración
Function FechaCal (MesCal As Integer, AñoCal As Integer) As String
    FechaCal = Mes(MesCal) + Str$(AñoCal)
End Function

'porque al imprimir el núm, si empieza por 0 el tipo no lo pone
'núm es Variant para darle versatilidad, y el byval para que admita de todo
'es recursiva
Function FunciónDecimal (ByVal núm As Variant) As String
    Select Case núm
    Case 0
	FunciónDecimal = "0"'antes ponía "00"
    Case Is > 0
	FunciónDecimal = IIf(núm >= 1, "", "0") + LTrim$(Str$(núm))
    Case Else'< 0
	FunciónDecimal = "-" + FunciónDecimal(-núm)
    End Select
End Function

'Inicia los valores de incertidumbre, fecha de próx cal, y el nº de
'   calibraciones
'los datos de entrada son: IniciarEstadoCal(i,k,m,a,c,n,v)
'i es la incertidumbre, k es el de I=kU; se imprime "I micras (k=?)", a menos
'   que k<1, entonces es que se trata de U en vez de I (para los pat cil y el
'   reloj, lo 1º es para el comp neu) [lo hace la función TextoIncertidumbre],
'   y si k=-1 entonces no pone la lista de calibraciones (se trata entonces de
'   la vent de calibrar el comp neu)
'm es el mes, a el año, de la próx cal
'c es el último comentario fijo
'v: la ventana
Sub IniciarEstadoCal (i As Single, k As Single, m As Integer, a As Integer, C As Integer, n As Integer, v As Form)
    Dim j As Integer, IncertidumbreTexto As String

    'escribe los textos para la última incertidumbre, y la fecha próx de cal
    Select Case C
    Case CalBuena
	IncertidumbreTexto = TextoIncertidumbre(i, k)
	j = DifDeFechas(m, a)
	Select Case j
	Case Is > TiempoDeAntelación'CalBuena
	    v.EtiquetaLastIncertidumbre = IncertidumbreTexto
	    v.EtiquetaFechaPróx = FechaCal(m, a)
	Case 0'CalCaducaYa
	    v.EtiquetaLastIncertidumbre = IncertidumbreTexto
	    v.EtiquetaFechaPróx = "Este mes"
	Case Is < 0'CalCaducada
	    v.EtiquetaLastIncertidumbre = "Caducada"
	    v.EtiquetaFechaPróx = "Cuanto antes"
	Case Else'>0 y <=antelación: CalCaducaPronto
	    v.EtiquetaLastIncertidumbre = IncertidumbreTexto
	    v.EtiquetaFechaPróx = "En" + Str$(j) + " mes" + Plural(j)
	End Select
    Case CalMala
	v.EtiquetaLastIncertidumbre.Caption = "Inaceptable"
	v.EtiquetaFechaPróx = "Cuanto antes"
    Case CalCero
	v.EtiquetaLastIncertidumbre.Caption = "Sin calibrar"
	v.EtiquetaFechaPróx = "Cuanto antes"
    End Select

    If k <> -1 Then 'pone la lista de las calibraciones
	v.EtiquetaNúmCalibraciones.Caption = Str$(n)
	v.ListaCalibraciones.Clear 'necesario para los pat cil
	If n = 0 Then
	    v.BotónConsultar.Enabled = False
	Else
	    v.BotónConsultar.Enabled = True
	    For j = 1 To n
		v.ListaCalibraciones.AddItem Str$(j), 0
		'el 0 es para que los ponga en orden inverso
	    Next j
	    v.ListaCalibraciones.ListIndex = 0
	End If
    End If

End Sub

'inicia los valores de comentario y meses, indicando el valor recomendado
'de tiempo, que será 48 para los patrones y 24 para los demás;
'además, añade la fecha al marco de resultados
Sub IniciarValoresComunesResultadoCal (tiempo As Integer, vent As Form)
    Dim i As Integer

    vent.MarcoResultados.Caption = vent.MarcoResultados.Caption + " [" + FechaActual() + "]"

    vent.BoxComentarioLargo.Text = "[Si lo desea, puede escribir aquí un comentario completo sobre esta calibración; de todas formas, borre este mensaje.]"

    For i = 1 To 12
	vent.ListaPróxMes.AddItem Mes(i)'ojo que el mes 1 es el 0, etc
    Next i
    For i = 0 To 6
	vent.ListaPróxAño.AddItem FunciónDecimal(Year(Now) + i)
    Next i
    vent.ListaPróxAño.ListIndex = tiempo / 12
    vent.ListaPróxMes.ListIndex = Month(Now) - 1'selecciona el mes actual
    Call CambioMarcoPróxCal(vent)
    
End Sub

Sub LeerConsultaPatCil (Pat As Integer, cal As Integer)

    screen.MousePointer = RelojArena

    Open NombreArchPatCal(Pat, cal) For Input As #1
	Input #1, CalPatCil.día
	Input #1, CalPatCil.Mes
	Input #1, CalPatCil.año
	Input #1, CalPatCil.DiámetroActual
	Input #1, CalPatCil.IdMedidora
	Input #1, CalPatCil.IncertidumbreMedidora
	Input #1, CalPatCil.FactorkMedidora
	Input #1, CalPatCil.TipoErrorDeDesviación
	Input #1, CalPatCil.FactorMultiplicador
	Input #1, CalPatCil.IncertidumbreEsfera
	Input #1, CalPatCil.FactorkEsfera
	Input #1, CalPatCil.PuntosPalpadoEsfera
	Input #1, CalPatCil.ErrorPalpadores
	Input #1, CalPatCil.PuntosPalpadoPatCil
	Input #1, CalPatCil.DiámetroMedio
	Input #1, CalPatCil.ErrorDiámetro
	Input #1, CalPatCil.Corrección
	Input #1, CalPatCil.DiámetroFinal
	Input #1, CalPatCil.Incertidumbre
	Input #1, CalPatCil.ComentarioFijo
	Input #1, CalPatCil.ComentarioLargo
	Input #1, CalPatCil.PróxMes
	Input #1, CalPatCil.PróxAño
	Input #1, CalPatCil.Encargado
	Input #1, CalPatCil.Supervisor
    Close #1

    screen.MousePointer = Def

End Sub

Sub LeerConsultaReloj (cal As Integer)
    Dim i As Integer

    screen.MousePointer = RelojArena

    Open NombreArchRelojCal(cal) For Input As #1

	'datos de la estructura
	Input #1, CalReloj.día
	Input #1, CalReloj.Mes
	Input #1, CalReloj.año
	Input #1, CalReloj.IdBloquesPatrón
	Input #1, CalReloj.IdPatrónPlanitud
	Input #1, CalReloj.NúmBloquesPatrón
	Input #1, CalReloj.IncertidumbrePatrones
	Input #1, CalReloj.FactorkPatrones
	Input #1, CalReloj.Incertidumbre
	Input #1, CalReloj.ComentarioFijo
	Input #1, CalReloj.ComentarioLargo
	Input #1, CalReloj.PróxMes
	Input #1, CalReloj.PróxAño
	Input #1, CalReloj.Encargado
	Input #1, CalReloj.Supervisor

	'medidas nominales de los bloques patrón
	ReDim BloquesPatrón(1 To CalReloj.NúmBloquesPatrón)
	For i = 1 To CalReloj.NúmBloquesPatrón
	    Input #1, BloquesPatrón(i)
	Next i

	'leer comunes (antes es necesario la siguiente definición)
	NúmSaltos = CalReloj.NúmBloquesPatrón - 1
	Call SóloLeerComunes

    Close #1

    screen.MousePointer = Def

End Sub

Sub LlamarAyuda (llamada As Integer)
    Dim NúmTema As Integer, título As String, texto As String

    On Error GoTo ErrorEnArchAyuda

    Open ArchAyuda For Input As #1
	Do
	    Input #1, NúmTema
	    Input #1, título
	    Input #1, texto
	Loop Until NúmTema = llamada
    Close #1

    VentAyuda.EtiquetaTema.Caption = título
    VentAyuda.BoxTexto.Text = texto
    VentAyuda.Show 1

    Exit Sub


ErrorEnArchAyuda:
    MsgBox "No se ha podido acceder al archivo que contiene la ayuda.", 16, "Aviso"
    Exit Sub

End Sub

Sub Main ()

    'INICIALIZACIÓN DE LOS VALORES GLOBALES


    'modificación 2/2 tras entrega proyecto:
    Directorio = app.path & "\"
    'fin modificación 2/2

    'archivo de la lista
    ArchLista = Directorio + NombreArchLista + Extensión


    'nombre de los modelos
    ModeloTexto(C60) = "ETAMIC C60"
    ModeloTexto(Estándar) = "Elemento Estándar"
    ModeloTexto(Universal) = "Cabezal Universal"


    'nombre de los errores
    ErrorDesviaciónTexto(DesviaciónMedia) = "Desviación media"
    ErrorDesviaciónTexto(DesviaciónTípica) = "Desviación típica"
    ErrorDesviaciónTexto(DesviaciónTípicaNmenos1) = "Desviación típica (n-1)"
    ErrorDesviaciónTexto(DesviaciónTípicaMedia) = "Desviación típica de la media 's'"
    ErrorDesviaciónTexto(DiferenciaDeRadiosExtremos) = "Diferencia de radios extremos"
    ErrorDesviaciónTexto(varianza) = "Varianza"
    ErrorDesviaciónTexto(VarianzaNmenos1) = "Varianza (n-1)"
    ErrorDesviaciónTexto(VarianzaTípicaMedia) = "Varianza típica de la media"
	 

    'meses
    Mes(1) = "Enero"
    Mes(2) = "Febrero"
    Mes(3) = "Marzo"
    Mes(4) = "Abril"
    Mes(5) = "Mayo"
    Mes(6) = "Junio"
    Mes(7) = "Julio"
    Mes(8) = "Agosto"
    Mes(9) = "Septiembre"
    Mes(10) = "Octubre"
    Mes(11) = "Noviembre"
    Mes(12) = "Diciembre"


    NuevaLínea = Chr$(10)



    VentAcercaDe.Show 1


    'comprobar que exista el archivo de ayuda
    On Error GoTo ErrorEnInicioArchAyuda
	ArchAyuda = Directorio + NombreArchAyuda + Extensión
	Open ArchAyuda For Input As #1
	Close #1
    On Error Resume Next'para que el programa no aborte


    VentListaCompNeu.Show 1


    End'game over, sefiní



ErrorEnInicioArchAyuda:
    MsgBox "No se ha podido acceder al archivo que contiene la ayuda." + NuevaLínea + "El programa seguirá ejecutándose, pero no se podrá disponer de ella.", 16, "Aviso"
    Resume Next

End Sub

Function NombreArchCompNeuCal (cal As Integer)
    NombreArchCompNeuCal = Subdirectorio + "Comp_" + FunciónDecimal(cal) + Extensión
End Function

'devuelve el nombre del archivo de datos de calibración de un pat cil, dados
'el nº del patrón, y el nº de la calibración
Function NombreArchPatCal (Pat As Integer, cal As Integer) As String
    NombreArchPatCal = Subdirectorio + "P-" + FunciónDecimal(Pat) + "_" + FunciónDecimal(cal) + Extensión
End Function

'devuelve el nombre del archivo de calibración correspondiente del reloj
Function NombreArchRelojCal (cal As Integer)
    NombreArchRelojCal = Subdirectorio + "Rloj_" + FunciónDecimal(cal) + Extensión
End Function

Function NombrePatCil (modo As Integer) As String
    Select Case modo
    Case CalibreMedida
	NombrePatCil = IIf(CompNeu.TipoCalibre, "Tampón", "Anillo")
    Case Minus1
	NombrePatCil = IIf(CompNeu.TipoCalibre, "anillo", "tampón")
    Case Mayusc1
	NombrePatCil = IIf(CompNeu.TipoCalibre, "Anillo", "Tampón")
    Case Minus2
	NombrePatCil = IIf(CompNeu.TipoCalibre, "anillos", "tampones")
    Case Mayusc2
	NombrePatCil = IIf(CompNeu.TipoCalibre, "Anillos", "Tampones")
    End Select
End Function

'el ByVal es para que se le pueda mandar una propiedad, ej: 'BarraTiempoDeAntelación.Value'
Function Plural (ByVal núm As Integer) As String
    Plural = IIf(núm = 1, "", "es")
End Function

'Esta sub se encargará de coger los valores de Referencia() y de
'MatrizSaltos(), llenar los valores nominales de cada salto llamando a la
'correspondientes ventanas, y hayar s y la incertidmbre U, según quien
'se calibre
'
'en sentido creciente (decreciente es el opuesto):
'medida del salto: Media de las medidas introducidas menos la de ref
'medida nominal del salto: Diferencia entre el pat móvil y el fijo
'em ambos sentidos, delta es el salto menos nominal, aunque al final lo
'importante es el valor absoluto
'
Sub RecogidaDeMedidas (quien As Integer) 'quien dice si es el comp neu (ParaElCompNeu),o el reloj (ParaElReloj)
    Dim sentido As Integer, salto As Integer, vez As Integer'para MatrizSaltos (están en orden)
    Dim s2 As Single, U2 As Single, Umáx As Single'para guardar la incertidumbre máxima (es cero al empezar)
    Dim delta As Single, suma As Single, suma2 As Single'(suma2 es suma de cuadrados); el código no es que sea el óptimo, pero es más claro


    ValorMedioMedidas = NúmVecesPorSalto + 1
    s_salto = NúmVecesPorSalto + 2
    U_salto = NúmVecesPorSalto + 3
    'también disponible el valor: 'NúmSaltos'


    'inicialización de la matriz de saltos (pone todo a cero)
    ReDim MatrizSaltos(creciente To decreciente, 1 To NúmSaltos, 0 To NúmVecesPorSalto + 3)

    'veces que se mide cada salto:
    VentMedidaDeReferencia.EtiquetaVeces.Caption = FunciónDecimal(NúmVecesPorSalto) + " veces."

    'escala a emplear
    VentMedidaDeReferencia.EtiquetaEscala.Caption = IIf(quien = Paraelcompneu, "comparador neumático", "reloj centesimal")

    'título de la ventana de medidas
    VentMedirSalto.Caption = "Medida de los " + IIf(quien = Paraelcompneu, "patrones cilíndricos", "bloques patrón")

    'cajas de coger medidas: títulos, enabled y color (el -1 se incluye ya en el For)
    For vez = 0 To NúmVecesPorSalto - 1
	VentMedirSalto.MarcoMedida(vez).Caption = FunciónDecimal(vez + 1) + "ª medida (µm)"
	'el texto de la caja ya se pone a vacío al principio del bucle
	VentMedirSalto.BoxMedida(vez).Enabled = True
	VentMedirSalto.BoxMedida(vez).BackColor = &HFFFF&'amarillo
    Next vez
    For vez = NúmVecesPorSalto To 15 'son 16 cajas, pero de 0 a 15
	VentMedirSalto.MarcoMedida(vez).Caption = ""
	VentMedirSalto.BoxMedida(vez).Text = ""
	VentMedirSalto.BoxMedida(vez).Enabled = False
	VentMedirSalto.BoxMedida(vez).BackColor = &H80000005'color de fondo del sistema, normalmente es el blanco
    Next vez


    'este es el bucle general:
    For sentido = creciente To decreciente
	
	'título de la ventana inicial
	VentMedidaDeReferencia.Caption = "Medidas en sentido " + IIf(sentido = creciente, "", "de") + "creciente"


	If quien = Paraelreloj Then
	    'etiqueta y cota del pat de ref en la 1ª ventana
	    VentMedidaDeReferencia.EtiquetaReferencia.Caption = "El bloque patrón " + IIf(sentido = creciente, "menor", "mayor")
	    VentMedidaDeReferencia.EtiquetaCotaPatRef.Caption = FunciónDecimal(IIf(sentido = creciente, BloquesPatrón(1), BloquesPatrón(CalReloj.NúmBloquesPatrón))) + micra
	    'contenido de la caja de texto para la medida de referencia
	    VentMedidaDeReferencia.BoxReferencia.Text = IIf(sentido = creciente, "0", "800")
	Else
	    'etiqueta y cota del pat cil de ref en la 1ª ventana
	    VentMedidaDeReferencia.EtiquetaReferencia.Caption = IIf(sentido = creciente, PatCilCal(1).Etiqueta, PatCilCal(CalCompNeu.NúmPatCil).Etiqueta)
	    VentMedidaDeReferencia.EtiquetaCotaPatRef.Caption = FunciónDecimal(IIf(sentido = creciente, PatCilCal(1).Diámetro, PatCilCal(CalCompNeu.NúmPatCil).Diámetro)) + micra
	    'contenido de la caja de texto para la medida de referencia
	    VentMedidaDeReferencia.BoxReferencia.Text = FunciónDecimal(40 * CompNeu.Apreciación * IIf(sentido = creciente, -1, 1))
	End If
	

	'llamada a la 1ª ventana
	VentMedidaDeReferencia.Show 1


	'etiqueta, cota y valor en la escala del pat de ref (en la 2ª ventana)
	VentMedirSalto.EtiquetaReferencia.Caption = VentMedidaDeReferencia.EtiquetaReferencia.Caption
	VentMedirSalto.EtiquetaCotaPatRef.Caption = VentMedidaDeReferencia.EtiquetaCotaPatRef.Caption
	VentMedirSalto.EtiquetaValorRef.Caption = FunciónDecimal(Referencia(sentido)) + micra


	For salto = 1 To NúmSaltos

	    'título del marco de datos generales del salto
	    VentMedirSalto.MarcoEstado.Caption = "Medidas en sentido " + IIf(sentido = creciente, "", "de") + "creciente: Salto nº" + Str$(salto) + " de" + Str$(NúmSaltos)

	    'texto de las cajas de medidas a vacío
	    For vez = 1 To NúmVecesPorSalto
		VentMedirSalto.BoxMedida(vez - 1).Text = ""
	    Next vez


	    If quien = Paraelreloj Then
		'valor nominal del salto
		MatrizSaltos(sentido, salto, ValorNominal) = IIf(sentido = creciente, BloquesPatrón(salto + 1) - BloquesPatrón(1), BloquesPatrón(CalReloj.NúmBloquesPatrón) - BloquesPatrón(CalReloj.NúmBloquesPatrón - salto))
		'etiqueta y cota del pat que se mide (en la 2ª ventana)
		VentMedirSalto.EtiquetaMide.Caption = "El" + Str$(IIf(sentido = creciente, salto + 1, CalReloj.NúmBloquesPatrón - salto)) + "º bloque patrón"
		VentMedirSalto.EtiquetaCotaPat.Caption = FunciónDecimal(IIf(sentido = creciente, BloquesPatrón(salto + 1), BloquesPatrón(CalReloj.NúmBloquesPatrón - salto))) + micra
		'U^2 debida a los patrones
		U2 = CalReloj.IncertidumbrePatrones / CalReloj.FactorkPatrones
		U2 = U2 * U2
	    Else
		'valor nominal del salto
		MatrizSaltos(sentido, salto, ValorNominal) = IIf(sentido = creciente, PatCilCal(salto + 1).Diámetro - PatCilCal(1).Diámetro, PatCilCal(CalCompNeu.NúmPatCil).Diámetro - PatCilCal(CalCompNeu.NúmPatCil - salto).Diámetro)
		'etiqueta y cota del pat cil que se mide (en la 2ª ventana)
		VentMedirSalto.EtiquetaMide.Caption = IIf(sentido = creciente, PatCilCal(salto + 1).Etiqueta, PatCilCal(CalCompNeu.NúmPatCil - salto).Etiqueta)
		VentMedirSalto.EtiquetaCotaPat.Caption = FunciónDecimal(IIf(sentido = creciente, PatCilCal(salto + 1).Diámetro, PatCilCal(CalCompNeu.NúmPatCil - salto).Diámetro)) + micra
		'U debida a:
		'el reloj:
		    'CalCompNeu.IncertidumbreReloj / 10 * CompNeu.Apreciación
		'pat cil de ref:
		    'PatCilCal(iif(sentido = creciente,1,CalCompNeu.NúmPatCil)).Incertidumbre
		'pat cil que se mide:
		    'PatCilCal(iif(sentido = creciente,salto + 1,CalCompNeu.NúmPatCil - salto)).Incertidumbre
		'U^2 resultante:
		U2 = (CalCompNeu.IncertidumbreReloj / 10 * CompNeu.Apreciación) * (CalCompNeu.IncertidumbreReloj / 10 * CompNeu.Apreciación) + (PatCilCal(IIf(sentido = creciente, 1, CalCompNeu.NúmPatCil)).Incertidumbre) * (PatCilCal(IIf(sentido = creciente, 1, CalCompNeu.NúmPatCil)).Incertidumbre) + (PatCilCal(IIf(sentido = creciente, salto + 1, CalCompNeu.NúmPatCil - salto)).Incertidumbre) * (PatCilCal(IIf(sentido = creciente, salto + 1, CalCompNeu.NúmPatCil - salto)).Incertidumbre)
	    End If



	    'valor en la escala del pat que se mide (en la 2ª ventana)
	    VentMedirSalto.EtiquetaValorEstimado.Caption = FunciónDecimal(Referencia(sentido) + IIf(sentido = creciente, 1, -1) * MatrizSaltos(sentido, salto, ValorNominal)) + micra
	    
	    'texto largo de la 2º vent, indica tanto la medida nominal del salto, como la escala a emplear
	    VentMedirSalto.EtiquetaTexto.Caption = "La diferencia de cotas de los patrones es" + Str$(MatrizSaltos(sentido, salto, ValorNominal)) + micra + ", pero la medida que se ha de indicar es la que marca el " + VentMedidaDeReferencia.EtiquetaEscala.Caption + " en su escala, que se estima en " + VentMedirSalto.EtiquetaValorEstimado.Caption + "."


	    'llamada a la 2ª ventana
	    VentMedirSalto.Show 1


	    'recogida de los datos, media, s, guardar en memoria...

	    'valores iniciales (aprovecho para meterlos aquí)
	    suma = 0
	    suma2 = 0

	    'recogida de los datos, y suma y suma2 de ellos
	    For vez = 1 To NúmVecesPorSalto
		MatrizSaltos(sentido, salto, vez) = Val(VentMedirSalto.BoxMedida(vez - 1).Text)'el -1 es porque empieza en 0
		suma = suma + MatrizSaltos(sentido, salto, vez)
		suma2 = suma2 + MatrizSaltos(sentido, salto, vez) * MatrizSaltos(sentido, salto, vez)
	    Next vez

	    'media (no del salto, sino de las medidas)
	    MatrizSaltos(sentido, salto, ValorMedioMedidas) = suma / NúmVecesPorSalto
	    'para el valor medio del salto, restarle 'referencia(sentido)'

	    's2 (tanto de las medidas como del salto)
	    s2 = w(NúmVecesPorSalto) * w(NúmVecesPorSalto) * (suma2 - suma * suma / NúmVecesPorSalto) / (NúmVecesPorSalto * (NúmVecesPorSalto - 1))

	    
	    'desviación al nominal (interesa su valor abs)
	    'el valor del salto (abs) es:
	    'IIf(sentido = creciente, 1, -1) * (MatrizSaltos(sentido, salto, ValorMedioMedidas) - Referencia(sentido))
	    delta = IIf(sentido = creciente, 1, -1) * (MatrizSaltos(sentido, salto, ValorMedioMedidas) - Referencia(sentido)) - MatrizSaltos(sentido, salto, ValorNominal)


	    'a U2 le mete 's2+[delta al nominal]^2 /3', que es lo que le falta para estar completa
	    U2 = U2 + s2 + delta * delta / 3

	    'grabar valores en la matriz
	    MatrizSaltos(sentido, salto, s_salto) = Sqr(s2)
	    MatrizSaltos(sentido, salto, U_salto) = Sqr(U2)

	    'ir controlando cuál es la U máxima (de todos los saltos y sentidos)
	    If MatrizSaltos(sentido, salto, U_salto) > Umáx Then Umáx = MatrizSaltos(sentido, salto, U_salto)

    Next salto, sentido


    'grabar la incertidumbre total final
    If quien = Paraelreloj Then
	CalReloj.Incertidumbre = Umáx * w(2 * NúmSaltos)
    Else 'para el comp neu, es U, aún no I, pues k se pone después
	CalCompNeu.Incertidumbre = Umáx * w(2 * NúmSaltos)
    End If

End Sub

'Graba los valores comunes al reloj y al comp neu:
'   NúmVecesPorSalto, Referencia() y MatrizSaltos()
'y los graba en el archivo abierto
Sub SóloGrabarComunes ()
    Dim sentido As Integer, salto As Integer, vez As Integer'para MatrizSaltos (están en orden)

    Write #1, NúmVecesPorSalto
    Write #1, Referencia(creciente)
    Write #1, Referencia(decreciente)

    For sentido = creciente To decreciente
	For salto = 1 To NúmSaltos
	    For vez = ValorNominal To U_salto
		Write #1, MatrizSaltos(sentido, salto, vez)
    Next vez, salto, sentido

End Sub

'Como la función anterior, pero para leer
Sub SóloLeerComunes ()
    Dim sentido As Integer, salto As Integer, vez As Integer'para MatrizSaltos (están en orden)

    Input #1, NúmVecesPorSalto
    Input #1, Referencia(creciente)
    Input #1, Referencia(decreciente)
    
    'al grabar no hace falta definirlos, al leer sí:
    ValorMedioMedidas = NúmVecesPorSalto + 1
    s_salto = NúmVecesPorSalto + 2
    U_salto = NúmVecesPorSalto + 3

    'preparar la matriz
    ReDim MatrizSaltos(creciente To decreciente, 1 To NúmSaltos, ValorNominal To U_salto)

    For sentido = creciente To decreciente
	For salto = 1 To NúmSaltos
	    For vez = ValorNominal To U_salto
		Input #1, MatrizSaltos(sentido, salto, vez)
    Next vez, salto, sentido

End Sub

Function TextoComentarioFijo (C As Integer) As String
    TextoComentarioFijo = "Calibración " + IIf(C = CalMala, "in", "") + "aceptable"
End Function

'devuele "I micras (k=?"), ó "U" (cuando k<1)
Function TextoIncertidumbre (i As Single, k As Single) As String
    TextoIncertidumbre = FunciónDecimal(i) + micra + IIf(k < 1, "", " (k=" + FunciónDecimal(k) + ")")
End Function

Function w (n As Integer) As Single
    Select Case n
    Case 2
	w = 7
    Case 3
	w = 2.3
    Case 4
	w = 1.7
    Case 5
	w = 1.4
    Case 6, 7
	w = 1.3
    Case 8, 9
	w = 1.2
    Case Is >= 10
	w = 1
    End Select
End Function

