*! 1.0.0 Ariel Linden 17May2025 

program markovpredict, rclass
	version 11.0
	syntax varname	,	///
		Past(string)	///
		[ 				///
		NOIsily]
		
	quietly {
		         
		local pastcnt: list sizeof past
		local rpast: list rsort past
		 
		// check if past values are among values in varname
		levelsof `varlist' , local(levt)
		forvalues i = 1 / `pastcnt' {	
			local a : word `i' of `past'
			if !`: list a in levt' {
				di as err "{bf:`a'} specified in {bf:past()} is not found in {bf:`varlist'}"
				exit 198
			}
		}	

		// empty ifs
		local ifs if

		// loop to get all the "if" qualifiers
		forvalues i = 1 / `pastcnt' {
			tempvar past`i'
		
			// generates past states
			gen `past`i'' = `varlist'[_n - `i']
			local a : word `i' of `past'
			if `i' < `pastcnt'  {
				local and &
			}
			else local and 
		
			// determine if entries in past are numeric or string
			local qq : word 1 of `past'
			capture confirm number `qq'
			if _rc == 0 {
				local ifs `ifs' `past`i'' == `a' `and'
			}
			else {
				local ifs `ifs' `past`i'' == "`a'" `and'
			}
		}	
		
*		noi di "`ifs'"
		// if the user wants to see how the next state was determined
		`noisily' tab `varlist' `ifs', nolabel
		if r(N) == 0 {
			di as err "there are no predictions based on the specified past states"
			exit 198
		}

		// the next state with the highest frequency is the prediction
		tempvar count
		preserve
		contract `varlist'  `ifs', freq(`count')
		gsort -`count'
		local predict = `varlist' in 1		
		noisily di as txt _n "   The prediction for the next state is {bf:`predict'}, based on the past `pastcnt' states (from most recent to most distant): {bf:`past'}		
		restore		

		// return result
		return local predict = "`predict'"

	} // end quietly
	
end