! makedaily.f90
! f90 program written by Tim Mitchell on 14.12.00
! last modified on 07.01.02
! tool to transform messy daily data sets into clean ones with a single formatting structure
! pgf90 -o ./../obs/makedaily filenames.f90 dayfiles.f90 time.f90 
!	cetgeneral.f90 ./../obs/makedaily.f90

program MakeDaily

use FileNames
use DAYFiles
use Time
use CETGeneral

implicit none

real, pointer, dimension (:,:,:)	:: MasterDaily, FileDaily

real, dimension (12)			:: LineReal

integer, pointer, dimension (:,:)	:: MonthLengths
integer, pointer, dimension (:)		:: YearAD, FileYearAD

integer, dimension (12)			:: LineInt

real, parameter :: MissVal = -999.0

character (len=80), parameter :: Blank = ""

real :: BlockMissVal, Multiplier
real :: OpMiss, OpEn, OpFrac

integer :: ReadStatus, AllocStat,MenuChoice
integer :: StartYear, EndYear, FirstYear, MasterYearN
integer :: BlockYearN, BlockStartAD, BlockEndAD, BlockStartX, BlockEndX
integer :: XYear, XMonth, XDay, XHeader, XFooter, XFileYear, XMasterYear
integer :: HeaderN, FooterN, StringLen
integer :: FileYear0,FileYear1,MasterYear0,MasterYear1
integer :: VariCode,PosChar,OpDays,QIntReal,ArraySize

character (len=80) :: GivenFile, OrigFile, LineFormat, Waste
character (len= 1) :: CharIntReal

!*******************************************************************************
! main

call Intro
call Select

contains

!*******************************************************************************
! check master array

subroutine CheckMaster

call GetMonthLengths (YearAD,MonthLengths)

OpMiss = 0.0
OpEn   = 0.0

do XYear = 1, MasterYearN
  do XMonth = 1, 12
    do XDay = 1, MonthLengths(XYear,XMonth)
      if (MasterDaily (XYear,XMonth,XDay) .NE. MissVal) then
        OpEn   = OpEn   + 1.0
      else
        OpMiss = OpMiss + 1.0
      end if
    end do
  end do
end do

OpFrac = 100.0 * OpMiss / (OpMiss + OpEn)
OpDays = OpMiss + OpEn

print "(a26,i8,f8.2)", "   > Data: days, missing%: ", OpDays, OpFrac
print*

deallocate (MonthLengths,stat=AllocStat)
if (AllocStat.NE.0) print*, "  > ##### ERROR: CheckMaster: Deallocation failure #####"

end subroutine CheckMaster

!*******************************************************************************
! intro

subroutine Intro

open (99,file="./../../../scratch/log-mde.dat",status="replace",action="write")

print*
print*, "  > ##### MakeDailyEasy.f90 ##### Tool for reformatting #####"
print*

print*, "  > We assume 12 months in a year and 31 days (max) in a month."
print*, "  > Enter the start and end years AD of the master array:"
do
	read (*,*,iostat=ReadStatus), StartYear, EndYear
	if (ReadStatus.LE.0 .AND. StartYear.LE.EndYear) exit
end do

MasterYearN = EndYear - StartYear + 1

allocate (YearAD(MasterYearN),stat=AllocStat)
if (AllocStat.NE.0) print*, "  > ##### ERROR: Intro: Allocation failure #####"

allocate (MasterDaily(MasterYearN,12,31),stat=AllocStat)
if (AllocStat.NE.0) print*, "  > ##### ERROR: Intro: Allocation failure #####"
MasterDaily = MissVal

do XMasterYear=1,MasterYearN
  YearAD (XMasterYear) = StartYear + XMasterYear - 1
end do

VariCode = MissVal

print*

end subroutine Intro

!*******************************************************************************
! load from .day file

subroutine LoadFromDAY

call LoadDAY      (Blank, VariCode, FileYearAD, FileDaily)

call CommonVecPer (FileYearAD,YearAD,FileYear0,FileYear1,MasterYear0,MasterYear1)

if (FileYear0.EQ.MissVal) then
  print*, "  > The loaded file has no period in common with the master array."
else
  print*, "  > Common period loaded into master array: ", FileYearAD(FileYear0), FileYearAD(FileYear1)
end if

do XFileYear = FileYear0, FileYear1
  XMasterYear = MasterYear0 + XFileYear - FileYear0
  
  do XMonth = 1, 12
    do XDay = 1, 31
      MasterDaily(XMasterYear,XMonth,XDay) = FileDaily(XFileYear,XMonth,XDay)
    end do
  end do
end do

deallocate (FileYearAD, FileDaily, stat=AllocStat)
if (AllocStat.NE.0) print*, "  > ##### ERROR: LoadFromDAY: Deallocation failure #####"

print*

end subroutine LoadFromDAY

!*******************************************************************************
! load original

subroutine LoadOriginal

BlockStartAD = FirstYear
BlockStartX  = FirstYear - StartYear + 1

open (2, file=OrigFile, status="old", access="sequential", form="formatted", action="read")
do
  print*
  print*, "  > New block. First year in block = ", BlockStartAD

  if (BlockStartAD.LT.YearAD(1)) then		! define BlockYearN, BlockEndAD
    BlockYearN = YearAD(1) - BlockStartAD
    BlockEndAD = BlockStartAD + BlockYearN - 1
    print*, "  > Block predates master array. Block length = ", BlockYearN
  else
    print*, "  > Enter the number of years in the block (0=end):"
    do
	read (*,*,iostat=ReadStatus), BlockYearN

	BlockEndAD = BlockStartAD + BlockYearN - 1	
	if (BlockEndAD.GT.YearAD(MasterYearN)) then
	  ReadStatus = 99
	  print*, "  > Block extends beyond master array. Try again."
	end if
	
	if (ReadStatus.LE.0) exit
    end do
  end if
  
  if (BlockYearN.NE.0) then
    print*, "  > Final year in block = ", BlockEndAD
    BlockEndX = BlockEndAD - BlockStartAD + BlockStartX		! define BlockEndX
    
    print*, "  > Enter the number of header lines per year:"
    do
	read (*,*,iostat=ReadStatus), HeaderN
	if (ReadStatus.LE.0) exit
    end do
    
    print*, "  > Enter the number of footer lines per year:"
    do
	read (*,*,iostat=ReadStatus), FooterN
	if (ReadStatus.LE.0) exit
    end do
    
    print*, "  > We assume one line of data per day with intercept and 12 months."
    print*, "  > Enter the data line format, e.g. (a10,12i5) or (a4,12f8.1)"
    do
	read (*,*,iostat=ReadStatus), LineFormat
	
	StringLen = len (trim(LineFormat))	

	PosChar = max (scan(LineFormat,'I'),scan(LineFormat,'i'),scan(LineFormat,'F'),scan(LineFormat,'f'))
	PosChar = max (scan(LineFormat,'E'),scan(LineFormat,'e'),PosChar)
	
	CharIntReal = ""
	if (PosChar.GT.0) CharIntReal = LineFormat(PosChar:PosChar)
	
	if (LineFormat(1:1).NE."(" .OR. LineFormat(StringLen:StringLen).NE.")") then
	    ReadStatus = 99
	    print*, "  > Format is unacceptable. Retry."
	else 
	  if      (CharIntReal.EQ.'I'.OR.CharIntReal.EQ.'i') then
	    QIntReal = 1
	  else if (CharIntReal.EQ.'F'.OR.CharIntReal.EQ.'f') then
	    QIntReal = 2
	  else if (CharIntReal.EQ.'F'.OR.CharIntReal.EQ.'f') then
	    QIntReal = 2
	  else
	    ReadStatus = 99
	    print*, "  > Format is unacceptable. Retry."
	  end if
	end if
	
	if (ReadStatus.LE.0) exit
    end do
    
    print*, "  > Enter the factor by which to multiply to obtain actual data: "
    do
	read (*,*,iostat=ReadStatus), Multiplier
	if (ReadStatus.LE.0) exit
    end do
    
    print*, "  > Enter the missing value: "
    do
	read (*,*,iostat=ReadStatus), BlockMissVal
	if (ReadStatus.LE.0) exit
    end do
    
    do XYear = BlockStartX, BlockEndX
      if (HeaderN.GT.0) then				! read headers
        do XHeader = 1, HeaderN
          read  (2, *), Waste
        end do
      end if
      
      do XDay = 1, 31					! read year
          if (QIntReal.EQ.1) read (2, LineFormat), Waste, (LineInt  (XMonth), XMonth=1,12)
          if (QIntReal.EQ.2) read (2, LineFormat), Waste, (LineReal (XMonth), XMonth=1,12)
           
          if (BlockStartX.GE.1) then
            do XMonth = 1, 12
              if (LineInt(XMonth).NE.BlockMissVal.AND.LineReal(XMonth).NE.BlockMissVal) then
                if (QIntReal.EQ.1) MasterDaily (XYear,XMonth,XDay) = real (LineInt(XMonth))
                if (QIntReal.EQ.2) MasterDaily (XYear,XMonth,XDay) = LineReal(XMonth)
                MasterDaily (XYear,XMonth,XDay) = MasterDaily (XYear,XMonth,XDay) * Multiplier
!              else
!              	MasterDaily (XYear,XMonth,XDay) = MissVal
              end if
            end do
          end if	
      end do
      
      LineReal = 0
      LineInt  = 0
      
      if (FooterN.GT.0) then				! read footers
        do XFooter = 1, FooterN
          read  (2, *), Waste
        end do
      end if
    end do
    
    BlockStartAD = BlockEndAD + 1
    BlockStartX  = BlockEndX  + 1
    if (BlockStartAD.GT.YearAD(MasterYearN)) then
    	print*, "  > End of block is also end of master array."
    	BlockYearN = 0
    end if
  end if
  
  if (BlockYearN.EQ.0) exit	
end do
close (2)

print*

end subroutine LoadOriginal

!*******************************************************************************
! main

subroutine Select

do
  print*, "  > Main menu. Make your choice. (0=list)"
  do
	read (*,*,iostat=ReadStatus), MenuChoice
	if (ReadStatus.LE.0) exit
  end do
	
  if      (MenuChoice.EQ.1)  then
    print*, "  > Are you sure? (1=no,2=yes)"
    do
	read (*,*,iostat=ReadStatus), MenuChoice
	if (ReadStatus.LE.0.AND.MenuChoice.GE.1.AND.MenuChoice.LE.2) exit
    end do
    if (MenuChoice.EQ.1) print*, "  > No changes made."
    if (MenuChoice.EQ.2) call Intro
  else if (MenuChoice.EQ.2)  then
    call SpecOriginal
    call LoadOriginal
  else if (MenuChoice.EQ.3)  then
    call LoadFromDAY
  else if (MenuChoice.EQ.4)  then
    call SaveDAY (Blank,VariCode,YearAD,MasterDaily)
    print*
  else if (MenuChoice.EQ.5)  then
    call CheckMaster
  else if (MenuChoice.NE.99) then
    print*, "  >  1. Reinitialise"
    print*, "  >  2. Load data from original file"
    print*, "  >  3. Load data from .day file"
    print*, "  >  4. Save to .day file"
    print*, "  >  5. Check master daily array"
    print*, "  > 99. Exit"
  end if
  
  if (MenuChoice.EQ.99) exit
end do

end subroutine Select

!*******************************************************************************
! spec original

subroutine SpecOriginal

print*, "  > Enter the original file path/name:"
do
	do
		read (*,*,iostat=ReadStatus), GivenFile
		if (ReadStatus.LE.0) exit
	end do
	
	inquire (file=GivenFile, name=OrigFile)
	open (1, file=OrigFile, status="old", access="sequential", form="formatted", &
			action="read", iostat=ReadStatus)
	if (ReadStatus .NE. 0) print*, "  > Cannot open file. Try again."
	if (ReadStatus .EQ. 0) close (1)
	if (ReadStatus .EQ. 0) exit
end do

print*, "  > Enter the first year AD in the file: "
do
	read (*,*,iostat=ReadStatus), FirstYear
	if (FirstYear.GT.YearAD(MasterYearN)) then
	  ReadStatus = 99
	  print*, "  > Year beyond master array. Try again."
	end if
	if (ReadStatus.LE.0) exit
end do

end subroutine SpecOriginal

!*******************************************************************************

end program MakeDaily
