<commit_before>package otto

import ()

func (self *_parser) ParseStatement() _node {

	switch self.Peek().Kind {
	case ";":
		self.Next()
		node := newEmptyNode()
		self.markNode(node)
		return node
	case "if":
		return self.ParseIf()
	case "do":
		return self.ParseDoWhile()
	case "while":
		return self.ParseWhile()
	case "for":
		return self.ParseForOrForIn()
	case "continue":
		return self.ParseContinue()
	case "with":
		return self.ParseWith()
	case "break":
		return self.ParseBreak()
	case "{":
		return self.ParseBlock()
	case "var":
		return self.ParseVariableStatement()
	case "function":
		self.ParseFunctionDeclaration()
		// TODO Should be FunctionDeclarationStatement
		node := newEmptyNode()
		self.markNode(node)
		return node
	case "switch":
		return self.ParseSwitch()
	case "return":
		return self.ParseReturnStatement()
	case "throw":
		return self.ParseThrow()
	case "try":
		return self.ParseTryCatch()
	}

	expression := self.ParseExpression()

	if identifier, yes := expression.(*_identifierNode); yes && self.Accept(":") {
		_labelSet := self.Scope()._labelSet
		label := identifier.Value
		if _labelSet[label] {
			panic(self.History(-2).newSyntaxError("Label '%s' has already been declared", label))
		}
		_labelSet[label] = true
		statement := self.ParseStatement()
		delete(_labelSet, label)
		{
			_labelSet = nil
			switch node := statement.(type) {
			case *_blockNode:
				_labelSet = node._labelSet
			case *_doWhileNode:
				_labelSet = node._labelSet
			case *_whileNode:
				_labelSet = node._labelSet
			case *_switchNode:
				_labelSet = node._labelSet
			case *_forNode:
				_labelSet = node._labelSet
			case *_forInNode:
				_labelSet = node._labelSet
			}
			if _labelSet != nil {
				_labelSet[label] = true
			}
		}
		return statement
	}

	self.ConsumeSemicolon()

	return expression
}

//func (self *_parser) parseSource() []_node {
//    nodeList := self.parseStatementUntil(func() bool {
//        return self.Match("EOF")
//    });
//    return self.ParseStatement()
//}

func (self *_parser) parseSourceElement() _node {
	return self.ParseStatement()
}

func (self *_parser) ParseTryCatch() _node {
	self.Expect("try")

	node := newTryCatchNode(self.ParseBlock())

	found := false
	if self.Accept("catch") {
		self.Expect("(")
		identifier := self.ConsumeIdentifier().Value
		self.Expect(")")
		node.Catch = newCatchNode(identifier, self.ParseBlock())
		found = true
	}

	if self.Accept("finally") {
		node.Finally = self.ParseBlock()
		found = true
	}

	if !found {
		panic(self.Peek().newSyntaxError("Missing catch or finally after try"))
	}

	return node
}

func (self *_parser) ParseWith() _node {
	self.Expect("with")

	return newWithNode(self.ParseExpression(), self.ParseStatement())
}

func (self *_parser) ParseContinue() _node {
	result := self.ParseContinueBreak("continue", func(kind string) _node { return newContinueNode(kind) })
	if self.Scope().InIteration {
		return result
	}
	panic(self.Peek().newSyntaxError("Illegal continue statement"))
}

func (self *_parser) ParseBreak() _node {
	result := self.ParseContinueBreak("break", func(kind string) _node { return newBreakNode(kind) })
	if self.Scope().InIteration || self.Scope().InSwitch {
		return result
	}
	panic(self.Peek().newSyntaxError("Illegal break statement"))
}

func (self *_parser) ParseContinueBreak(kind string, _newNode func(string) _node) _node {
	self.Expect(kind)

	if self.Accept(";") || self.Accept("\n") {
		return _newNode("")
	}

	label := ""
	if self.Match("identifier") {
		identifier := self.ConsumeIdentifier()
		label = identifier.Value
		if !self.Scope().HasLabel(label) {
			panic(self.History(-1).newSyntaxError("Undefined label '%s'", label))
		}
	}

	self.ConsumeSemicolon()

	return _newNode(label)
}

func (self *_parser) parseInFunction(parse func() _node) _node {
	in := self.Scope().InFunction
	self.Scope().InFunction = true
	defer func() {
		self.Scope().InFunction = in
	}()
	return parse()
}

func (self *_parser) parseInSwitch(parse func() _node) _node {
	in := self.Scope().InSwitch
	self.Scope().InSwitch = true
	defer func() {
		self.Scope().InSwitch = in
	}()
	return parse()
}

func (self *_parser) parseInIteration(parse func() _node) []_node {
	in := self.Scope().InIteration
	self.Scope().InIteration = true
	defer func() {
		self.Scope().InIteration = in
	}()
	switch node := parse().(type) {
	case *_blockNode:
		return node.Body
	default:
		return []_node{node}
	}
}

func (self *_parser) ParseDoWhile() _node {
	self.Expect("do")
	body := self.parseInIteration(func() _node {
		return self.ParseStatement()
	})
	self.Expect("while")
	self.Expect("(")
	test := self.ParseExpression()
	self.Expect(")")

	node := newDoWhileNode(test, body)
	node._labelSet[""] = true
	return node
}

func (self *_parser) ParseWhile() _node {
	self.Expect("while")
	self.Expect("(")
	test := self.ParseExpression()
	self.Expect(")")
	body := self.parseInIteration(func() _node {
		return self.ParseStatement()
	})

	node := newWhileNode(test, body)
	node._labelSet[""] = true
	return node
}

func (self *_parser) ParseIf() _node {
	self.Expect("if")
	self.Expect("(")
	node := newIfNode(self.ParseExpression(), nil)
	self.Expect(")")
	node.Consequent = self.ParseStatement()
	if self.Accept("else") {
		node.Alternate = self.ParseStatement()
	}

	return node
}

func (self *_parser) parseStatementUntil(stop func() bool) []_node {
	list := []_node{}
	for {
		if stop() {
			break
		}
		list = append(list, self.ParseStatement())
	}
	return list
}

func (self *_parser) ParseBlock() *_blockNode {
	node := newBlockNode()
	self.markNode(node)

	self.Expect("{")
	node.Body = self.parseStatementUntil(func() bool {
		return self.Accept("}")
	})

	return node
}

func (self *_parser) ParseReturnStatement() _node {
	self.Expect("return")

	if !self.Scope().InFunction {
		panic(self.History(-1).newSyntaxError("Illegal return statement"))
	}

	node := newReturnNode()
	self.markNode(node)

	if self.Match("\n") {
		return node
	}

	if !self.Match(";") {
		if !self.Match("}") && !self.Match("EOF") {
			node.Argument = self.ParseExpression()
		}
	}

	self.ConsumeSemicolon()

	return node
}

func (self *_parser) ParseThrow() _node {
	self.Expect("throw")

	if self.Match("\n") {
		// TODO Better error message
		panic(self.Peek().newSyntaxError("Illegal newline after throw"))
	}

	node := newThrowNode(self.ParseExpression())
	self.markNode(node)

	self.ConsumeSemicolon()

	return node
}

func (self *_parser) ParseSwitch() _node {
	self.Expect("switch")

	self.Expect("(")
	discriminant := self.ParseExpression()
	self.Expect(")")

	switchNode := newSwitchNode(discriminant)
	self.markNode(switchNode)

	self.Expect("{")

	self.parseInSwitch(func() _node {
		for i := 0; true; i++ {
			if self.Accept("}") {
				break
			}

			result := self.ParseCase()
			if result.Test == nil {
				if switchNode.Default != -1 {
					panic(hereBeDragons("Already saw a default:"))
				}
				switchNode.Default = i
			}
			switchNode.AddCase(result)
		}
		return nil
	})

	switchNode._labelSet[""] = true
	return switchNode
}

func (self *_parser) ParseCase() *_caseNode {

	var node *_caseNode
	if self.Accept("default") {
		node = newDefaultCaseNode()
		self.markNode(node)
	} else {
		self.Expect("case")
		node = newCaseNode(self.ParseExpression())
		self.markNode(node)
	}
	self.Expect(":")

	node.Body = self.parseStatementUntil(func() bool {
		return false ||
			self.Match("EOF") ||
			self.Match("}") ||
			self.Match("default") ||
			self.Match("case")
	})

	return node
}

func (self *_parser) ParseVariable() *_variableDeclarationNode {
	node := newVariableDeclarationNode(self.ConsumeIdentifier().Value)
	self.markNode(node)

	for _, value := range []string{"=", ":="} {
		if self.Accept(value) {
			node.Operator = value
			node.Initializer = self.ParseAssignmentExpression()
			break
		}
	}

	return node
}

func (self *_parser) ParseVariableDeclaration() *_variableDeclarationListNode {
	self.Expect("var")

	node := newVariableDeclarationListNode()
	self.markNode(node)

	for {
		variable := self.ParseVariable()
		node.VariableList = append(node.VariableList, variable)
		self.Scope().AddVariable(variable.Identifier)

		if !self.Accept(",") {
			break
		}
	}

	return node
}

func (self *_parser) ParseVariableStatement() *_variableDeclarationListNode {

	node := self.ParseVariableDeclaration()

	self.ConsumeSemicolon()

	return node
}

func (self *_parser) ParseFunction(declare bool) _node {

	self.Expect("function")

	functionNode := newFunctionNode()
	self.markNode(functionNode)

	identifier := ""
	if self.Match("identifier") {
		identifier = self.ConsumeIdentifier().Value
		if declare {
			self.Scope().AddFunction(identifier, functionNode)
		}
	} else if declare {
		// Trigger a panic, because we really should see
		// an identifier here
		self.Expect("identifier")
	}

	token := self.Peek()
	if token.Kind != "(" {
		panic(self.Unexpected(token))
	}

	self.Expect("(")
	for !self.Accept(")") {
		identifier := self.ConsumeIdentifier().Value
		functionNode.AddParameter(identifier)
		if identifier == "arguments" {
			functionNode.ArgumentsIsParameter = true
		}
		if !self.Match(")") {
			self.Expect(",")
		}
	}

	{
		self.EnterScope()
		if !declare && identifier != "" {
			self.Scope().AddFunction(identifier, functionNode)
		}
		defer self.LeaveScope()
		self.parseInFunction(func() _node {
			functionNode.Body = self.ParseBlock().Body
			return nil
		})
		functionNode.VariableList = self.Scope().VariableList
		functionNode.FunctionList = self.Scope().FunctionList
	}

	return functionNode
}

/*func (self *_parser) ParseFunctionParameterList() []string {*/
/*    parameterList := []string{}*/

/*    for !self.Match("EOF") {*/
/*        identifier := self.ConsumeIdentifier().Value*/
/*        parameterList = append(parameterList, identifier)*/
/*    }*/

/*    return parameterList*/
/*}*/

func (self *_parser) ParseFunctionDeclaration() {
	self.ParseFunction(true)
}

func (self *_parser) parseForIn(into _node) *_forInNode {

	// Already have consumed "<into> in"

	source := self.ParseExpression()
	self.Expect(")")

	body := self.parseInIteration(func() _node {
		return self.ParseStatement()
	})

	node := newForInNode(into, source, body)
	self.markNode(node)
	node._labelSet[""] = true
	return node
}

func (self *_parser) parseFor(initial _node) *_forNode {

	// Already have consumed "<initial> ;"

	var test, update _node

	if !self.Match(";") {
		test = self.ParseExpression()
	}
	self.Expect(";")

	if !self.Match(")") {
		update = self.ParseExpression()
	}
	self.Expect(")")

	body := self.parseInIteration(func() _node {
		return self.ParseStatement()
	})

	node := newForNode(initial, test, update, body)
	self.markNode(node)
	node._labelSet[""] = true
	return node
}

func (self *_parser) ParseForOrForIn() _node {
	self.Expect("for")
	self.Expect("(")

	var left _node

	isIn := false
	if !self.Match(";") {
		previousAllowIn := self.Scope().AllowIn
		self.Scope().AllowIn = false
		if self.Match("var") {
			declarationList := self.ParseVariableDeclaration()
			if len(declarationList.VariableList) == 1 && self.Accept("in") {
				isIn = true
				// We only want (there should be only) one _declaration
				// (12.2 Variable Statement)
				left = declarationList.VariableList[0]
			} else {
				left = declarationList
			}
		} else {
			left = self.ParseExpression()
			isIn = self.Accept("in")
		}
		self.Scope().AllowIn = previousAllowIn
	}

	if !isIn {
		self.Expect(";")
		return self.parseFor(left)
	} else {
		switch left.Type() {
		case nodeIdentifier, nodeDotMember, nodeBracketMember, nodeVariableDeclaration:
		default:
			panic(self.History(-1).newSyntaxError("Invalid left-hand side in for-in"))
		}
	}

	return self.parseForIn(left)
}
<commit_msg>Fix: parse_statement.go:184: function ends without a return statement<commit_after>package otto

import ()

func (self *_parser) ParseStatement() _node {

	switch self.Peek().Kind {
	case ";":
		self.Next()
		node := newEmptyNode()
		self.markNode(node)
		return node
	case "if":
		return self.ParseIf()
	case "do":
		return self.ParseDoWhile()
	case "while":
		return self.ParseWhile()
	case "for":
		return self.ParseForOrForIn()
	case "continue":
		return self.ParseContinue()
	case "with":
		return self.ParseWith()
	case "break":
		return self.ParseBreak()
	case "{":
		return self.ParseBlock()
	case "var":
		return self.ParseVariableStatement()
	case "function":
		self.ParseFunctionDeclaration()
		// TODO Should be FunctionDeclarationStatement
		node := newEmptyNode()
		self.markNode(node)
		return node
	case "switch":
		return self.ParseSwitch()
	case "return":
		return self.ParseReturnStatement()
	case "throw":
		return self.ParseThrow()
	case "try":
		return self.ParseTryCatch()
	}

	expression := self.ParseExpression()

	if identifier, yes := expression.(*_identifierNode); yes && self.Accept(":") {
		_labelSet := self.Scope()._labelSet
		label := identifier.Value
		if _labelSet[label] {
			panic(self.History(-2).newSyntaxError("Label '%s' has already been declared", label))
		}
		_labelSet[label] = true
		statement := self.ParseStatement()
		delete(_labelSet, label)
		{
			_labelSet = nil
			switch node := statement.(type) {
			case *_blockNode:
				_labelSet = node._labelSet
			case *_doWhileNode:
				_labelSet = node._labelSet
			case *_whileNode:
				_labelSet = node._labelSet
			case *_switchNode:
				_labelSet = node._labelSet
			case *_forNode:
				_labelSet = node._labelSet
			case *_forInNode:
				_labelSet = node._labelSet
			}
			if _labelSet != nil {
				_labelSet[label] = true
			}
		}
		return statement
	}

	self.ConsumeSemicolon()

	return expression
}

//func (self *_parser) parseSource() []_node {
//    nodeList := self.parseStatementUntil(func() bool {
//        return self.Match("EOF")
//    });
//    return self.ParseStatement()
//}

func (self *_parser) parseSourceElement() _node {
	return self.ParseStatement()
}

func (self *_parser) ParseTryCatch() _node {
	self.Expect("try")

	node := newTryCatchNode(self.ParseBlock())

	found := false
	if self.Accept("catch") {
		self.Expect("(")
		identifier := self.ConsumeIdentifier().Value
		self.Expect(")")
		node.Catch = newCatchNode(identifier, self.ParseBlock())
		found = true
	}

	if self.Accept("finally") {
		node.Finally = self.ParseBlock()
		found = true
	}

	if !found {
		panic(self.Peek().newSyntaxError("Missing catch or finally after try"))
	}

	return node
}

func (self *_parser) ParseWith() _node {
	self.Expect("with")

	return newWithNode(self.ParseExpression(), self.ParseStatement())
}

func (self *_parser) ParseContinue() _node {
	result := self.ParseContinueBreak("continue", func(kind string) _node { return newContinueNode(kind) })
	if self.Scope().InIteration {
		return result
	}
	panic(self.Peek().newSyntaxError("Illegal continue statement"))
}

func (self *_parser) ParseBreak() _node {
	result := self.ParseContinueBreak("break", func(kind string) _node { return newBreakNode(kind) })
	if self.Scope().InIteration || self.Scope().InSwitch {
		return result
	}
	panic(self.Peek().newSyntaxError("Illegal break statement"))
}

func (self *_parser) ParseContinueBreak(kind string, _newNode func(string) _node) _node {
	self.Expect(kind)

	if self.Accept(";") || self.Accept("\n") {
		return _newNode("")
	}

	label := ""
	if self.Match("identifier") {
		identifier := self.ConsumeIdentifier()
		label = identifier.Value
		if !self.Scope().HasLabel(label) {
			panic(self.History(-1).newSyntaxError("Undefined label '%s'", label))
		}
	}

	self.ConsumeSemicolon()

	return _newNode(label)
}

func (self *_parser) parseInFunction(parse func() _node) _node {
	in := self.Scope().InFunction
	self.Scope().InFunction = true
	defer func() {
		self.Scope().InFunction = in
	}()
	return parse()
}

func (self *_parser) parseInSwitch(parse func() _node) _node {
	in := self.Scope().InSwitch
	self.Scope().InSwitch = true
	defer func() {
		self.Scope().InSwitch = in
	}()
	return parse()
}

func (self *_parser) parseInIteration(parse func() _node) []_node {
	in := self.Scope().InIteration
	self.Scope().InIteration = true
	defer func() {
		self.Scope().InIteration = in
	}()
	switch node := parse().(type) {
	case *_blockNode:
		return node.Body
	default:
		return []_node{node}
	}
	panic("")
}

func (self *_parser) ParseDoWhile() _node {
	self.Expect("do")
	body := self.parseInIteration(func() _node {
		return self.ParseStatement()
	})
	self.Expect("while")
	self.Expect("(")
	test := self.ParseExpression()
	self.Expect(")")

	node := newDoWhileNode(test, body)
	node._labelSet[""] = true
	return node
}

func (self *_parser) ParseWhile() _node {
	self.Expect("while")
	self.Expect("(")
	test := self.ParseExpression()
	self.Expect(")")
	body := self.parseInIteration(func() _node {
		return self.ParseStatement()
	})

	node := newWhileNode(test, body)
	node._labelSet[""] = true
	return node
}

func (self *_parser) ParseIf() _node {
	self.Expect("if")
	self.Expect("(")
	node := newIfNode(self.ParseExpression(), nil)
	self.Expect(")")
	node.Consequent = self.ParseStatement()
	if self.Accept("else") {
		node.Alternate = self.ParseStatement()
	}

	return node
}

func (self *_parser) parseStatementUntil(stop func() bool) []_node {
	list := []_node{}
	for {
		if stop() {
			break
		}
		list = append(list, self.ParseStatement())
	}
	return list
}

func (self *_parser) ParseBlock() *_blockNode {
	node := newBlockNode()
	self.markNode(node)

	self.Expect("{")
	node.Body = self.parseStatementUntil(func() bool {
		return self.Accept("}")
	})

	return node
}

func (self *_parser) ParseReturnStatement() _node {
	self.Expect("return")

	if !self.Scope().InFunction {
		panic(self.History(-1).newSyntaxError("Illegal return statement"))
	}

	node := newReturnNode()
	self.markNode(node)

	if self.Match("\n") {
		return node
	}

	if !self.Match(";") {
		if !self.Match("}") && !self.Match("EOF") {
			node.Argument = self.ParseExpression()
		}
	}

	self.ConsumeSemicolon()

	return node
}

func (self *_parser) ParseThrow() _node {
	self.Expect("throw")

	if self.Match("\n") {
		// TODO Better error message
		panic(self.Peek().newSyntaxError("Illegal newline after throw"))
	}

	node := newThrowNode(self.ParseExpression())
	self.markNode(node)

	self.ConsumeSemicolon()

	return node
}

func (self *_parser) ParseSwitch() _node {
	self.Expect("switch")

	self.Expect("(")
	discriminant := self.ParseExpression()
	self.Expect(")")

	switchNode := newSwitchNode(discriminant)
	self.markNode(switchNode)

	self.Expect("{")

	self.parseInSwitch(func() _node {
		for i := 0; true; i++ {
			if self.Accept("}") {
				break
			}

			result := self.ParseCase()
			if result.Test == nil {
				if switchNode.Default != -1 {
					panic(hereBeDragons("Already saw a default:"))
				}
				switchNode.Default = i
			}
			switchNode.AddCase(result)
		}
		return nil
	})

	switchNode._labelSet[""] = true
	return switchNode
}

func (self *_parser) ParseCase() *_caseNode {

	var node *_caseNode
	if self.Accept("default") {
		node = newDefaultCaseNode()
		self.markNode(node)
	} else {
		self.Expect("case")
		node = newCaseNode(self.ParseExpression())
		self.markNode(node)
	}
	self.Expect(":")

	node.Body = self.parseStatementUntil(func() bool {
		return false ||
			self.Match("EOF") ||
			self.Match("}") ||
			self.Match("default") ||
			self.Match("case")
	})

	return node
}

func (self *_parser) ParseVariable() *_variableDeclarationNode {
	node := newVariableDeclarationNode(self.ConsumeIdentifier().Value)
	self.markNode(node)

	for _, value := range []string{"=", ":="} {
		if self.Accept(value) {
			node.Operator = value
			node.Initializer = self.ParseAssignmentExpression()
			break
		}
	}

	return node
}

func (self *_parser) ParseVariableDeclaration() *_variableDeclarationListNode {
	self.Expect("var")

	node := newVariableDeclarationListNode()
	self.markNode(node)

	for {
		variable := self.ParseVariable()
		node.VariableList = append(node.VariableList, variable)
		self.Scope().AddVariable(variable.Identifier)

		if !self.Accept(",") {
			break
		}
	}

	return node
}

func (self *_parser) ParseVariableStatement() *_variableDeclarationListNode {

	node := self.ParseVariableDeclaration()

	self.ConsumeSemicolon()

	return node
}

func (self *_parser) ParseFunction(declare bool) _node {

	self.Expect("function")

	functionNode := newFunctionNode()
	self.markNode(functionNode)

	identifier := ""
	if self.Match("identifier") {
		identifier = self.ConsumeIdentifier().Value
		if declare {
			self.Scope().AddFunction(identifier, functionNode)
		}
	} else if declare {
		// Trigger a panic, because we really should see
		// an identifier here
		self.Expect("identifier")
	}

	token := self.Peek()
	if token.Kind != "(" {
		panic(self.Unexpected(token))
	}

	self.Expect("(")
	for !self.Accept(")") {
		identifier := self.ConsumeIdentifier().Value
		functionNode.AddParameter(identifier)
		if identifier == "arguments" {
			functionNode.ArgumentsIsParameter = true
		}
		if !self.Match(")") {
			self.Expect(",")
		}
	}

	{
		self.EnterScope()
		if !declare && identifier != "" {
			self.Scope().AddFunction(identifier, functionNode)
		}
		defer self.LeaveScope()
		self.parseInFunction(func() _node {
			functionNode.Body = self.ParseBlock().Body
			return nil
		})
		functionNode.VariableList = self.Scope().VariableList
		functionNode.FunctionList = self.Scope().FunctionList
	}

	return functionNode
}

/*func (self *_parser) ParseFunctionParameterList() []string {*/
/*    parameterList := []string{}*/

/*    for !self.Match("EOF") {*/
/*        identifier := self.ConsumeIdentifier().Value*/
/*        parameterList = append(parameterList, identifier)*/
/*    }*/

/*    return parameterList*/
/*}*/

func (self *_parser) ParseFunctionDeclaration() {
	self.ParseFunction(true)
}

func (self *_parser) parseForIn(into _node) *_forInNode {

	// Already have consumed "<into> in"

	source := self.ParseExpression()
	self.Expect(")")

	body := self.parseInIteration(func() _node {
		return self.ParseStatement()
	})

	node := newForInNode(into, source, body)
	self.markNode(node)
	node._labelSet[""] = true
	return node
}

func (self *_parser) parseFor(initial _node) *_forNode {

	// Already have consumed "<initial> ;"

	var test, update _node

	if !self.Match(";") {
		test = self.ParseExpression()
	}
	self.Expect(";")

	if !self.Match(")") {
		update = self.ParseExpression()
	}
	self.Expect(")")

	body := self.parseInIteration(func() _node {
		return self.ParseStatement()
	})

	node := newForNode(initial, test, update, body)
	self.markNode(node)
	node._labelSet[""] = true
	return node
}

func (self *_parser) ParseForOrForIn() _node {
	self.Expect("for")
	self.Expect("(")

	var left _node

	isIn := false
	if !self.Match(";") {
		previousAllowIn := self.Scope().AllowIn
		self.Scope().AllowIn = false
		if self.Match("var") {
			declarationList := self.ParseVariableDeclaration()
			if len(declarationList.VariableList) == 1 && self.Accept("in") {
				isIn = true
				// We only want (there should be only) one _declaration
				// (12.2 Variable Statement)
				left = declarationList.VariableList[0]
			} else {
				left = declarationList
			}
		} else {
			left = self.ParseExpression()
			isIn = self.Accept("in")
		}
		self.Scope().AllowIn = previousAllowIn
	}

	if !isIn {
		self.Expect(";")
		return self.parseFor(left)
	} else {
		switch left.Type() {
		case nodeIdentifier, nodeDotMember, nodeBracketMember, nodeVariableDeclaration:
		default:
			panic(self.History(-1).newSyntaxError("Invalid left-hand side in for-in"))
		}
	}

	return self.parseForIn(left)
}
<|endoftext|>


<commit_before>package kutil

import (
	"fmt"
	"io/ioutil"
	"os"
	"os/exec"
	"path/filepath"
	"runtime"
	"strings"
)

type UtilError string

func (err UtilError) Error() string { return "Utils Error: " + string(err) }

func ProcessName() string {
	file := os.Args[0]
	i := strings.LastIndex(file, "\\")
	j := strings.LastIndex(file, "/")
	if j < i {
		file = file[i+1:]
	} else if j > i {
		file = file[j+1:]
	}
	i = strings.LastIndex(file, ".")
	if i > 0 {
		file = file[0:i]
	}
	return file
}

func DefaultPidFileName() string {
	file := ProcessName()
	pidFile := "/var/run/"
	if runtime.GOOS == "windows" {
		pidFile = "c:\\" + file + ".pid"
	} else {
		pidFile += file + ".pid"
	}
	return pidFile
}

func ProcessFile() string {
	file, _ := exec.LookPath(os.Args[0])
	path, _ := filepath.Abs(file)
	return path
}

func ProcessPath() string {
	path := filepath.Dir(ProcessFile())
	return path
}

func WritePidFile(myFile string, pid int) (err error) {
	return ioutil.WriteFile(myFile, []byte(fmt.Sprintf("%d", pid)), 0644)
}

func CheckWritePidPermission(pidFile string) error {
	if len(pidFile) <= 0 {
		pidFile = DefaultPidFileName()
	}
	file := pidFile + ".tmp"
	if err := ioutil.WriteFile(file, []byte(fmt.Sprintf("%d", 0)), 0644); err != nil {
		return UtilError("had no permission to write pid file")
	}
	os.Remove(file)
	return nil
}

func ExecProcess(background bool, file string, args ...string) (int, error) {
	fmt.Println("args:", args, "-Len:", len(args))
	filePath, _ := filepath.Abs(file)
	cmd := exec.Command(filePath, args...)
	if background {
		cmd.Stdin = nil //给新进程设置文件描述符，可以重定向到文件中
		cmd.Stdout = nil
		cmd.Stderr = nil
	} else {
		cmd.Stdin = os.Stdin //给新进程设置文件描述符，可以重定向到文件中
		cmd.Stdout = os.Stdout
		cmd.Stderr = os.Stderr
	}
	err := cmd.Start()
	if err == nil {
		return cmd.Process.Pid, nil
	}
	return -1, err
}

func TryToRunAsDaemon(key string) (int, error) {
	key = strings.ToLower(key)
	var argsNew []string
	var bFind bool = false
	for _, arg := range os.Args {
		arg = strings.ToLower(arg)
		if arg == key {
			bFind = true
		} else {
			argsNew = append(argsNew, arg)
		}
	}
	if bFind {
		if err := CheckWritePidPermission(DefaultPidFileName()); err != nil {
			return -1, UtilError("has no permission to write pid file")
		}
		if pid, err := ExecProcess(true, ProcessFile(), argsNew...); err == nil {
			return pid, nil
		}
		return -2, UtilError("failed to execute pid file")
	}
	return 0, nil
}

func StartProcess(background bool, file string, args []string) (*os.Process, error) {
	filePath, _ := filepath.Abs(file)
	if background {
		return os.StartProcess(filePath, args, &os.ProcAttr{Files: []*os.File{nil, nil, nil}})
	}
	return os.StartProcess(filePath, args, &os.ProcAttr{Files: []*os.File{os.Stdin, os.Stdout, os.Stderr}})
}

func WaitProcess(background bool, file string, args []string) ([]byte, error) {
	filePath, _ := filepath.Abs(file)
	cmd := exec.Command(filePath, args...)
	if background {
		cmd.Stdin = nil //给新进程设置文件描述符，可以重定向到文件中
		cmd.Stdout = nil
		cmd.Stderr = nil
	} else {
		cmd.Stdin = os.Stdin //给新进程设置文件描述符，可以重定向到文件中
		cmd.Stdout = os.Stdout
		cmd.Stderr = os.Stderr
	}
	//cmd.Run()不能返回内容，而Output可以返回内容。
	return cmd.Output()
}
<commit_msg>在RunasDaemon时增加pid文件权限检查。<commit_after>package kutil

import (
	"fmt"
	"io/ioutil"
	"os"
	"os/exec"
	"path/filepath"
	"runtime"
	"strings"
)

type UtilError string

func (err UtilError) Error() string { return "Utils Error: " + string(err) }

func ProcessName() string {
	file := os.Args[0]
	i := strings.LastIndex(file, "\\")
	j := strings.LastIndex(file, "/")
	if j < i {
		file = file[i+1:]
	} else if j > i {
		file = file[j+1:]
	}
	i = strings.LastIndex(file, ".")
	if i > 0 {
		file = file[0:i]
	}
	return file
}

func DefaultPidFileName() string {
	file := ProcessName()
	pidFile := "/var/run/"
	if runtime.GOOS == "windows" {
		pidFile = "c:\\" + file + ".pid"
	} else {
		pidFile += file + ".pid"
	}
	return pidFile
}

func ProcessFile() string {
	file, _ := exec.LookPath(os.Args[0])
	path, _ := filepath.Abs(file)
	return path
}

func ProcessPath() string {
	path := filepath.Dir(ProcessFile())
	return path
}

func WritePidFile(myFile string, pid int) (err error) {
	return ioutil.WriteFile(myFile, []byte(fmt.Sprintf("%d", pid)), 0644)
}

func CheckWritePidPermission(pidFile string) error {
	if len(pidFile) <= 0 {
		pidFile = DefaultPidFileName()
	}
	file := pidFile + ".tmp"
	if err := ioutil.WriteFile(file, []byte(fmt.Sprintf("%d", 0)), 0644); err != nil {
		return UtilError("had no permission to write pid file")
	}
	os.Remove(file)
	return nil
}

func ExecProcess(background bool, file string, args ...string) (int, error) {
	fmt.Println("args:", args, "-Len:", len(args))
	filePath, _ := filepath.Abs(file)
	cmd := exec.Command(filePath, args...)
	if background {
		cmd.Stdin = nil //给新进程设置文件描述符，可以重定向到文件中
		cmd.Stdout = nil
		cmd.Stderr = nil
	} else {
		cmd.Stdin = os.Stdin //给新进程设置文件描述符，可以重定向到文件中
		cmd.Stdout = os.Stdout
		cmd.Stderr = os.Stderr
	}
	err := cmd.Start()
	if err == nil {
		return cmd.Process.Pid, nil
	}
	return -1, err
}

func TryToRunAsDaemon(key, pidFile string) int {
	key = strings.ToLower(key)
	var argsNew []string
	var bFind bool = false
	for _, arg := range os.Args {
		arg = strings.ToLower(arg)
		if arg == key {
			bFind = true
		} else {
			argsNew = append(argsNew, arg)
		}
	}
	if bFind {
		if err := CheckWritePidPermission(pidFile); err != nil {
			return -1
		}
		if pid, err := ExecProcess(true, ProcessFile(), argsNew...); err == nil {
			return pid
		}
		return -2
	}
	return 0
}

func StartProcess(background bool, file string, args []string) (*os.Process, error) {
	filePath, _ := filepath.Abs(file)
	if background {
		return os.StartProcess(filePath, args, &os.ProcAttr{Files: []*os.File{nil, nil, nil}})
	}
	return os.StartProcess(filePath, args, &os.ProcAttr{Files: []*os.File{os.Stdin, os.Stdout, os.Stderr}})
}

func WaitProcess(background bool, file string, args []string) ([]byte, error) {
	filePath, _ := filepath.Abs(file)
	cmd := exec.Command(filePath, args...)
	if background {
		cmd.Stdin = nil //给新进程设置文件描述符，可以重定向到文件中
		cmd.Stdout = nil
		cmd.Stderr = nil
	} else {
		cmd.Stdin = os.Stdin //给新进程设置文件描述符，可以重定向到文件中
		cmd.Stdout = os.Stdout
		cmd.Stderr = os.Stderr
	}
	//cmd.Run()不能返回内容，而Output可以返回内容。
	return cmd.Output()
}
<|endoftext|>


<commit_before>package infermedica

import (
	"encoding/json"
	"net/http"
)

type LabTestsRes struct {
	ID         string      `json:"id"`
	Name       string      `json:"name"`
	CommonName string      `json:"common_name"`
	Category   string      `json:"category"`
	Results    []LabResult `json:"results"`
}

type LabResult struct {
	ID   string `json:"id"`
	Type string `json:"type"`
}

func (a *App) LabTests() (*[]LabTestsRes, error) {
	req, err := a.prepareRequest("GET", "lab_tests", nil)
	if err != nil {
		return nil, err
	}
	client := &http.Client{}
	res, err := client.Do(req)
	if err != nil {
		return nil, err
	}
	r := []LabTestsRes{}
	err = json.NewDecoder(res.Body).Decode(&r)
	if err != nil {
		return nil, err
	}
	return &r, nil
}

func (a *App) LabTestByID(id string) (*LabTestsRes, error) {
	req, err := a.prepareRequest("GET", "lab_tests/"+id, nil)
	if err != nil {
		return nil, err
	}
	client := &http.Client{}
	res, err := client.Do(req)
	if err != nil {
		return nil, err
	}
	r := LabTestsRes{}
	err = json.NewDecoder(res.Body).Decode(&r)
	if err != nil {
		return nil, err
	}
	return &r, nil
}
<commit_msg>added lab tests recommend endpoint handler<commit_after>package infermedica

import (
	"encoding/json"
	"net/http"

	"github.com/pkg/errors"
)

type LabTestsRes struct {
	ID         string      `json:"id"`
	Name       string      `json:"name"`
	CommonName string      `json:"common_name"`
	Category   string      `json:"category"`
	Results    []LabResult `json:"results"`
}

type LabResult struct {
	ID   string `json:"id"`
	Type string `json:"type"`
}

func (a *App) LabTests() (*[]LabTestsRes, error) {
	req, err := a.prepareRequest("GET", "lab_tests", nil)
	if err != nil {
		return nil, err
	}
	client := &http.Client{}
	res, err := client.Do(req)
	if err != nil {
		return nil, err
	}
	r := []LabTestsRes{}
	err = json.NewDecoder(res.Body).Decode(&r)
	if err != nil {
		return nil, err
	}
	return &r, nil
}

func (a *App) LabTestByID(id string) (*LabTestsRes, error) {
	req, err := a.prepareRequest("GET", "lab_tests/"+id, nil)
	if err != nil {
		return nil, err
	}
	client := &http.Client{}
	res, err := client.Do(req)
	if err != nil {
		return nil, err
	}
	r := LabTestsRes{}
	err = json.NewDecoder(res.Body).Decode(&r)
	if err != nil {
		return nil, err
	}
	return &r, nil
}

type LabTestsRecommendRes struct {
	Recommended *[]LabTestsRecommendation `json:"recommended"`
	Obligatory  *[]LabTestsRecommendation `json:"obligatory"`
}
type LabTestsRecommendation struct {
	PanelID  string       `json:"panel_id"`
	Name     string       `json:"name"`
	Position int          `json:"position"`
	LabTests []LabTestsID `json:"lab_tests"`
}
type LabTestsID struct {
	ID string `json:"id"`
}

// Recommend is a func to request lab test recommendations for given data
func (a *App) Recommend(dr DiagnosisReq) (*LabTestsRecommendRes, error) {
	if !dr.Sex.IsValid() {
		return nil, errors.New("Unexpected value for Sex")
	}
	req, err := a.prepareRequest("POST", "lab_tests/recommend", dr)
	if err != nil {
		return nil, err
	}
	client := &http.Client{}
	res, err := client.Do(req)
	if err != nil {
		return nil, err
	}
	r := LabTestsRecommendRes{}
	err = json.NewDecoder(res.Body).Decode(&r)
	if err != nil {
		return nil, err
	}
	return &r, nil
}
<|endoftext|>


<commit_before>package main

import (
	"database/sql"
	"encoding/json"
	"flag"
	"fmt"
	"html/template"
	"io/ioutil"
	"net/http"
	"os"
	"regexp"
	"strings"
	"time"

	_ "github.com/mattn/go-sqlite3"
)

var settings struct {
	DailyTarget int
	Database    string
}

func init() {
	flag.IntVar(&settings.DailyTarget, "target", 900, "The number of words to write daily")
	flag.StringVar(&settings.Database, "db", "diary.db", "The name of the database file")
}

func main() {
	flag.Parse()

	db, err := sql.Open("sqlite3", settings.Database)
	if err != nil {
		panic(err)
	}

	_, err = db.Exec("CREATE TABLE IF NOT EXISTS entries (date TEXT PRIMARY KEY, text TEXT, words INTEGER)")
	if err != nil {
		panic(err)
	}

	if flag.NArg() >= 1 {
		cmd := flag.Arg(0)
		if cmd == "import" {
			importEntry(db)
			return
		}
	}

	http.HandleFunc("/", func(w http.ResponseWriter, req *http.Request) {
		renderEntry(w, req, db, time.Now())
	})

	http.HandleFunc("/day/", func(w http.ResponseWriter, req *http.Request) {
		parts := strings.SplitN(req.URL.Path, "/", 3)
		if len(parts) != 3 {
			w.WriteHeader(http.StatusNotFound)
			w.Write([]byte(http.StatusText(http.StatusNotFound)))
			return
		}

		date, err := time.Parse("2006-01-02", parts[2])
		if err != nil {
			w.WriteHeader(http.StatusNotFound)
			fmt.Fprintf(w, "No such day: %q\n", parts[2])
			fmt.Fprintf(os.Stderr, "Invalid date: %q: %s\n", date, err)
			return
		}

		renderEntry(w, req, db, date)
	})

	http.HandleFunc("/save", func(w http.ResponseWriter, req *http.Request) {
		var entry map[string]string
		dec := json.NewDecoder(req.Body)
		err := dec.Decode(&entry)
		if err != nil {
			respondWithError(w, http.StatusBadRequest, err)
			return
		}

		text, ok := entry["text"]
		if !ok {
			respondWithError(w, http.StatusBadRequest, fmt.Errorf("Missing field 'text'"))
			return
		}

		now := time.Now()
		err = saveEntry(db, now, text)
		if err != nil {
			respondWithError(w, http.StatusInternalServerError, fmt.Errorf("%s", http.StatusText(http.StatusInternalServerError)))
			return
		}

		enc := json.NewEncoder(w)
		err = enc.Encode(map[string]string{"message": "saved post", "time": now.Format(time.RFC3339)})
		if err != nil {
			fmt.Fprintf(os.Stderr, "Error: %s\n", err)
		}
	})

	http.ListenAndServe("localhost:12345", nil)
}

func respondWithError(w http.ResponseWriter, status int, err error) {
	res := map[string]string{"error": err.Error()}
	out, err := json.Marshal(res)
	if err != nil {
		w.WriteHeader(http.StatusInternalServerError)
		fmt.Fprintf(w, "{\"error\": %q}", http.StatusText(http.StatusInternalServerError))
		return
	}
	w.WriteHeader(status)
	w.Write(out)
}

func renderEntry(w http.ResponseWriter, req *http.Request, db *sql.DB, date time.Time) {
	now := time.Now()
	isSameDay := date.Format("2006-01-02") == now.Format("2006-01-02")

	if isSameDay && req.URL.Path != "/" {
		w.Header().Set("Location", "/")
		w.WriteHeader(http.StatusTemporaryRedirect)
		return
	}

	days := daysOfMonth(date)
	annotatedDays, err := annotateDays(db, days)
	if err != nil {
		fmt.Fprintf(os.Stderr, "Error: %s\n", err)
	}

	text := ""
	words := 0
	rows, err := db.Query("SELECT text, words FROM entries WHERE date = ?", date.Format("2006-01-02"))
	if err != nil {
		fmt.Fprintf(os.Stderr, "Error: %s\n", err)
	}
	defer rows.Close()

	if rows.Next() {
		err = rows.Scan(&text, &words)
		if err != nil {
			fmt.Fprintf(os.Stderr, "Error: %s\n", err)
		}
	}

	err = indexTmpl.Execute(w, map[string]interface{}{
		"Title": fmt.Sprintf("%d words", settings.DailyTarget),

		"Now":  now,
		"Day":  date,
		"Days": annotatedDays,

		"Text":  text,
		"Words": words,

		"Editable": isSameDay,
	})
	if err != nil {
		fmt.Fprintf(os.Stderr, "Error: %s\n", err)
	}
}

func saveEntry(db *sql.DB, date time.Time, text string) error {
	_, err := db.Exec("INSERT OR REPLACE INTO entries VALUES (?, ?, ?)", date.Format("2006-01-02"), text, countWords(text))
	return err
}

func importEntry(db *sql.DB) {
	if flag.NArg() < 2 {
		fmt.Fprintf(os.Stderr, "Usage: %s import <date>\n", os.Args[0])
		os.Exit(1)
	}

	rawDate := flag.Arg(1)
	date, err := time.Parse("2006-01-02", rawDate)
	if err != nil {
		fmt.Fprintf(os.Stderr, "Error: invalid date '%s': %s\n", rawDate, err)
		os.Exit(1)
	}

	f := os.Stdin
	if flag.NArg() >= 3 {
		f, err = os.Open(flag.Arg(2))
		if err != nil {
			fmt.Fprintf(os.Stderr, "Error: %s\n", err)
			os.Exit(1)
		}
	}
	defer f.Close()

	text, err := ioutil.ReadAll(f)
	if err != nil {
		fmt.Fprintf(os.Stderr, "Error: reading %s: %s\n", f.Name(), err)
		os.Exit(1)
	}

	err = saveEntry(db, date, string(text))
	if err != nil {
		fmt.Fprintf(os.Stderr, "Error: saving entry: %s\n", err)
		os.Exit(1)
	}
}

var indexTmpl = template.Must(template.New("index").Parse(`<!doctype html>

		<meta charset="utf-8" />
		<title>{{ .Title }}</title>

{{ .Title }}

{{ .Day.Format "January 2006" }}

			{{ $now := .Now }}
			{{ range $day := .Days -}}
				{{ if (and ($day.Date.Before $now) (gt $day.Words 0)) }}

{{ $day.Date.Day }}

				{{- else }}

{{ $day.Date.Day }}

				{{- end }}
			{{ end }}

{{ .Day.Format "Monday, January 2, 2006" }}

				{{ if not .Editable }}
This day is over, so you can't change what you wrote anymore.  Try again today.
{{ end }}
				<textarea id="editor" {{ if not .Editable }}disabled{{ end }}>{{ .Text }}</textarea>

					0 words

				Made with <3 by strange adventures.  —  /about

`))

var wordSeperator = regexp.MustCompile(`\s+`)

func countWords(text string) int {
	ws := wordSeperator.Split(text, -1)
	c := 0
	for _, w := range ws {
		if w != "" {
			c += 1
		}
	}
	return c
}

func daysOfMonth(t time.Time) []time.Time {
	s := time.Date(t.Year(), t.Month(), 1, 0, 0, 0, 0, t.Location())
	e := s.AddDate(0, 1, 0)
	ts := make([]time.Time, 0, 31)
	for s.Before(e) {
		ts = append(ts, s)
		s = s.AddDate(0, 0, 1)
	}
	return ts
}

type Day struct {
	Date  time.Time
	Words int
}

func (d Day) Classes(now time.Time) string {
	var classes string
	if d.Date.Before(now) {
		classes = "past"
	} else {
		classes = "future"
	}

	if d.Words >= 1 {
		classes += " written"
	}

	if d.Words >= settings.DailyTarget {
		classes += " yay"
	}

	return classes
}

func annotateDays(db *sql.DB, days []time.Time) ([]Day, error) {
	rows, err := db.Query("SELECT date, words FROM entries WHERE date >= ? AND date <= ?", days[0].Format("2006-01-02"), days[len(days)-1].Format("2006-01-02"))
	if err != nil {
		return nil, err
	}
	defer rows.Close()

	var day string
	var words int
	if rows.Next() {
		err = rows.Scan(&day, &words)
		if err != nil {
			return nil, err
		}
	}

	annotatedDays := make([]Day, len(days))
	for i, t := range days {
		d := Day{Date: t, Words: 0}

		if t.Format("2006-01-02") == day {
			d.Words = words

			if rows.Next() {
				err = rows.Scan(&day, &words)
				if err != nil {
					return nil, err
				}
			}
		}

		annotatedDays[i] = d
	}

	return annotatedDays, nil
}
<commit_msg>Ensure the text is always completely visible<commit_after>package main

import (
	"database/sql"
	"encoding/json"
	"flag"
	"fmt"
	"html/template"
	"io/ioutil"
	"net/http"
	"os"
	"regexp"
	"strings"
	"time"

	_ "github.com/mattn/go-sqlite3"
)

var settings struct {
	DailyTarget int
	Database    string
}

func init() {
	flag.IntVar(&settings.DailyTarget, "target", 900, "The number of words to write daily")
	flag.StringVar(&settings.Database, "db", "diary.db", "The name of the database file")
}

func main() {
	flag.Parse()

	db, err := sql.Open("sqlite3", settings.Database)
	if err != nil {
		panic(err)
	}

	_, err = db.Exec("CREATE TABLE IF NOT EXISTS entries (date TEXT PRIMARY KEY, text TEXT, words INTEGER)")
	if err != nil {
		panic(err)
	}

	if flag.NArg() >= 1 {
		cmd := flag.Arg(0)
		if cmd == "import" {
			importEntry(db)
			return
		}
	}

	http.HandleFunc("/", func(w http.ResponseWriter, req *http.Request) {
		renderEntry(w, req, db, time.Now())
	})

	http.HandleFunc("/day/", func(w http.ResponseWriter, req *http.Request) {
		parts := strings.SplitN(req.URL.Path, "/", 3)
		if len(parts) != 3 {
			w.WriteHeader(http.StatusNotFound)
			w.Write([]byte(http.StatusText(http.StatusNotFound)))
			return
		}

		date, err := time.Parse("2006-01-02", parts[2])
		if err != nil {
			w.WriteHeader(http.StatusNotFound)
			fmt.Fprintf(w, "No such day: %q\n", parts[2])
			fmt.Fprintf(os.Stderr, "Invalid date: %q: %s\n", date, err)
			return
		}

		renderEntry(w, req, db, date)
	})

	http.HandleFunc("/save", func(w http.ResponseWriter, req *http.Request) {
		var entry map[string]string
		dec := json.NewDecoder(req.Body)
		err := dec.Decode(&entry)
		if err != nil {
			respondWithError(w, http.StatusBadRequest, err)
			return
		}

		text, ok := entry["text"]
		if !ok {
			respondWithError(w, http.StatusBadRequest, fmt.Errorf("Missing field 'text'"))
			return
		}

		now := time.Now()
		err = saveEntry(db, now, text)
		if err != nil {
			respondWithError(w, http.StatusInternalServerError, fmt.Errorf("%s", http.StatusText(http.StatusInternalServerError)))
			return
		}

		enc := json.NewEncoder(w)
		err = enc.Encode(map[string]string{"message": "saved post", "time": now.Format(time.RFC3339)})
		if err != nil {
			fmt.Fprintf(os.Stderr, "Error: %s\n", err)
		}
	})

	http.ListenAndServe("localhost:12345", nil)
}

func respondWithError(w http.ResponseWriter, status int, err error) {
	res := map[string]string{"error": err.Error()}
	out, err := json.Marshal(res)
	if err != nil {
		w.WriteHeader(http.StatusInternalServerError)
		fmt.Fprintf(w, "{\"error\": %q}", http.StatusText(http.StatusInternalServerError))
		return
	}
	w.WriteHeader(status)
	w.Write(out)
}

func renderEntry(w http.ResponseWriter, req *http.Request, db *sql.DB, date time.Time) {
	now := time.Now()
	isSameDay := date.Format("2006-01-02") == now.Format("2006-01-02")

	if isSameDay && req.URL.Path != "/" {
		w.Header().Set("Location", "/")
		w.WriteHeader(http.StatusTemporaryRedirect)
		return
	}

	days := daysOfMonth(date)
	annotatedDays, err := annotateDays(db, days)
	if err != nil {
		fmt.Fprintf(os.Stderr, "Error: %s\n", err)
	}

	text := ""
	words := 0
	rows, err := db.Query("SELECT text, words FROM entries WHERE date = ?", date.Format("2006-01-02"))
	if err != nil {
		fmt.Fprintf(os.Stderr, "Error: %s\n", err)
	}
	defer rows.Close()

	if rows.Next() {
		err = rows.Scan(&text, &words)
		if err != nil {
			fmt.Fprintf(os.Stderr, "Error: %s\n", err)
		}
	}

	err = indexTmpl.Execute(w, map[string]interface{}{
		"Title": fmt.Sprintf("%d words", settings.DailyTarget),

		"Now":  now,
		"Day":  date,
		"Days": annotatedDays,

		"Text":  text,
		"Words": words,

		"Editable": isSameDay,
	})
	if err != nil {
		fmt.Fprintf(os.Stderr, "Error: %s\n", err)
	}
}

func saveEntry(db *sql.DB, date time.Time, text string) error {
	_, err := db.Exec("INSERT OR REPLACE INTO entries VALUES (?, ?, ?)", date.Format("2006-01-02"), text, countWords(text))
	return err
}

func importEntry(db *sql.DB) {
	if flag.NArg() < 2 {
		fmt.Fprintf(os.Stderr, "Usage: %s import <date>\n", os.Args[0])
		os.Exit(1)
	}

	rawDate := flag.Arg(1)
	date, err := time.Parse("2006-01-02", rawDate)
	if err != nil {
		fmt.Fprintf(os.Stderr, "Error: invalid date '%s': %s\n", rawDate, err)
		os.Exit(1)
	}

	f := os.Stdin
	if flag.NArg() >= 3 {
		f, err = os.Open(flag.Arg(2))
		if err != nil {
			fmt.Fprintf(os.Stderr, "Error: %s\n", err)
			os.Exit(1)
		}
	}
	defer f.Close()

	text, err := ioutil.ReadAll(f)
	if err != nil {
		fmt.Fprintf(os.Stderr, "Error: reading %s: %s\n", f.Name(), err)
		os.Exit(1)
	}

	err = saveEntry(db, date, string(text))
	if err != nil {
		fmt.Fprintf(os.Stderr, "Error: saving entry: %s\n", err)
		os.Exit(1)
	}
}

var indexTmpl = template.Must(template.New("index").Parse(`<!doctype html>

		<meta charset="utf-8" />
		<title>{{ .Title }}</title>

{{ .Title }}

{{ .Day.Format "January 2006" }}

			{{ $now := .Now }}
			{{ range $day := .Days -}}
				{{ if (and ($day.Date.Before $now) (gt $day.Words 0)) }}

{{ $day.Date.Day }}

				{{- else }}

{{ $day.Date.Day }}

				{{- end }}
			{{ end }}

{{ .Day.Format "Monday, January 2, 2006" }}

				{{ if not .Editable }}
This day is over, so you can't change what you wrote anymore.  Try again today.
{{ end }}
				<textarea id="editor" {{ if not .Editable }}disabled{{ end }}>{{ .Text }}</textarea>

					0 words

				Made with <3 by strange adventures.  —  /about

`))

var wordSeperator = regexp.MustCompile(`\s+`)

func countWords(text string) int {
	ws := wordSeperator.Split(text, -1)
	c := 0
	for _, w := range ws {
		if w != "" {
			c += 1
		}
	}
	return c
}

func daysOfMonth(t time.Time) []time.Time {
	s := time.Date(t.Year(), t.Month(), 1, 0, 0, 0, 0, t.Location())
	e := s.AddDate(0, 1, 0)
	ts := make([]time.Time, 0, 31)
	for s.Before(e) {
		ts = append(ts, s)
		s = s.AddDate(0, 0, 1)
	}
	return ts
}

type Day struct {
	Date  time.Time
	Words int
}

func (d Day) Classes(now time.Time) string {
	var classes string
	if d.Date.Before(now) {
		classes = "past"
	} else {
		classes = "future"
	}

	if d.Words >= 1 {
		classes += " written"
	}

	if d.Words >= settings.DailyTarget {
		classes += " yay"
	}

	return classes
}

func annotateDays(db *sql.DB, days []time.Time) ([]Day, error) {
	rows, err := db.Query("SELECT date, words FROM entries WHERE date >= ? AND date <= ?", days[0].Format("2006-01-02"), days[len(days)-1].Format("2006-01-02"))
	if err != nil {
		return nil, err
	}
	defer rows.Close()

	var day string
	var words int
	if rows.Next() {
		err = rows.Scan(&day, &words)
		if err != nil {
			return nil, err
		}
	}

	annotatedDays := make([]Day, len(days))
	for i, t := range days {
		d := Day{Date: t, Words: 0}

		if t.Format("2006-01-02") == day {
			d.Words = words

			if rows.Next() {
				err = rows.Scan(&day, &words)
				if err != nil {
					return nil, err
				}
			}
		}

		annotatedDays[i] = d
	}

	return annotatedDays, nil
}
<|endoftext|>


<commit_before>package ldp

import (
	"errors"
	"fmt"
	"io"
	"ldpserver/rdf"
	"ldpserver/textstore"
	"ldpserver/util"
	"log"
	"strings"
	"time"
)

var NodeNotFoundError = errors.New("Node not found")
var DuplicateNodeError = errors.New("Node already exists")
var EtagMissingError = errors.New("Missing Etag")
var EtagMismatchError = errors.New("Etag mismatch")
var ServerManagedPropertyError = errors.New("Attempted to update server managed property")

const metaFile = "meta.rdf"
const dataFile = "data.txt"
const etagPredicate = "<" + rdf.ServerETagUri + ">"
const rdfTypePredicate = "<" + rdf.RdfTypeUri + ">"
const contentTypePredicate = "<" + rdf.ServerContentTypeUri + ">"

type Node struct {
	isRdf   bool
	uri     string
	headers map[string][]string
	graph   rdf.RdfGraph
	binary  string // should be []byte or reader

	settings Settings
	rootUri  string // http://localhost/
	store    textstore.Store

	isBasicContainer   bool
	isDirectContainer  bool
	membershipResource string
	hasMemberRelation  string
	// TODO isMemberOfRelation string
}

func (node Node) AddChild(child Node) error {
	triple := rdf.NewTriple("<"+node.uri+">", "<"+rdf.LdpContainsUri+">", "<"+child.uri+">")
	err := node.store.AppendToFile(metaFile, triple.StringLn())
	if err != nil {
		return err
	}

	if node.isDirectContainer {
		return node.addDirectContainerChild(child)
	}
	return nil
}

func (node Node) Content() string {
	if node.isRdf {
		return node.graph.String()
	}
	return node.binary
}

func (node Node) Metadata() string {
	return node.graph.String()
}

func (node Node) nonRdfContentType() string {
	if node.isRdf {
		panic("Cannot call NonRdfContentType() for an RDF node")
	}
	triple, found := node.graph.FindTriple("<"+node.uri+">", contentTypePredicate)
	if !found {
		return "application/binary"
	}
	return triple.Object()
}

func (node Node) DebugString() string {
	if !node.isRdf {
		return fmt.Sprintf("Non-RDF: %s", node.uri)
	}

	triples := ""
	for i, triple := range node.graph {
		triples += fmt.Sprintf("%d %s\n", i, triple)
	}
	debugString := fmt.Sprintf("RDF: %s\n %s", node.uri, triples)
	return debugString
}

func (node *Node) Etag() string {
	subject := "<" + node.uri + ">"
	etag, etagFound := node.graph.GetObject(subject, "<"+rdf.ServerETagUri+">")
	if !etagFound {
		panic(fmt.Sprintf("No etag found for node %s", node.uri))
	}
	return etag
}

func (node Node) HasTriple(predicate, object string) bool {
	return node.graph.HasTriple("<"+node.uri+">", predicate, object)
}

func (node Node) Headers() map[string][]string {
	return node.headers
}

func (node Node) IsBasicContainer() bool {
	return node.isBasicContainer
}

func (node Node) IsDirectContainer() bool {
	return node.isDirectContainer
}

func (node Node) IsRdf() bool {
	return node.isRdf
}

func (node Node) Uri() string {
	return node.uri
}

func (node *Node) Patch(triples string) error {
	if !node.isRdf {
		return errors.New("Cannot PATCH non-RDF Source")
	}

	graph, err := rdf.StringToGraph(triples, "<"+node.uri+">")
	if err != nil {
		return err
	}

	// This is pretty useless as-is since it does not allow to update
	// a triple. It always adds triples.
	// Also, there are some triples that can exist only once (e.g. direct container triples)
	// and this code does not validate them.
	node.graph.Append(graph)

	// write it to disk
	if err := node.writeToDisk(nil); err != nil {
		return err
	}

	return nil
}

func (node Node) Path() string {
	return util.PathFromUri(node.rootUri, node.uri)
}

func (node Node) String() string {
	return node.uri
}

func (node *Node) appendTriple(predicate, object string) {
	node.graph.AppendTriple2("<"+node.uri+">", predicate, object)
}

func (node *Node) setETag() {
	node.graph.SetObject("<"+node.uri+">", etagPredicate, calculateEtag())
}

func GetNode(settings Settings, path string) (Node, error) {
	node := newNode(settings, path)
	err := node.loadNode(true)
	return node, err
}

func GetHead(settings Settings, path string) (Node, error) {
	node := newNode(settings, path)
	err := node.loadNode(false)
	return node, err
}

func NewRdfNode(settings Settings, triples string, path string) (Node, error) {
	node := newNode(settings, path)
	graph, err := rdf.StringToGraph(triples, "<"+node.uri+">")
	if err != nil {
		return Node{}, err
	}
	return node, node.writeRdfToDisk(graph)
}

func NewNonRdfNode(settings Settings, reader io.ReadCloser, path, triples string) (Node, error) {
	node := newNode(settings, path)
	graph, err := rdf.StringToGraph(triples, "<"+node.uri+">")
	if err != nil {
		return Node{}, err
	}
	return node, node.writeNonRdfToDisk(graph, reader)
}

func ReplaceNonRdfNode(settings Settings, reader io.ReadCloser, path, etag, triples string) (Node, error) {
	node, err := GetHead(settings, path)
	if err != nil {
		return Node{}, err
	}

	if node.isRdf {
		return Node{}, errors.New("Cannot replace RDF source with a Non-RDF source")
	}

	if etag == "" {
		return Node{}, EtagMissingError
	}

	if node.Etag() != etag {
		// log.Printf("Cannot replace RDF source. Etag mismatch. Expected: %s. Found: %s", node.Etag(), etag)
		return Node{}, EtagMismatchError
	}

	var graph rdf.RdfGraph
	if triples != "" {
		graph, err = rdf.StringToGraph(triples, "<"+node.uri+">")
		if err != nil {
			return Node{}, err
		}
	}

	return node, node.writeNonRdfToDisk(graph, reader)
}

func ReplaceRdfNode(settings Settings, triples string, path string, etag string) (Node, error) {
	node, err := GetNode(settings, path)
	if err != nil {
		return Node{}, err
	}

	if !node.isRdf {
		return Node{}, errors.New("Cannot replace non-RDF source with an RDF source")
	}

	if etag == "" {
		return Node{}, EtagMissingError
	}

	if node.Etag() != etag {
		// log.Printf("Cannot replace RDF source. Etag mismatch. Expected: %s. Found: %s", node.Etag(), etag)
		return Node{}, EtagMismatchError
	}

	graph, err := rdf.StringToGraph(triples, "<"+node.uri+">")
	if err != nil {
		return Node{}, err
	}

	// TODO: What other server-managed properties should we handle?
	if graph.HasPredicate("<"+node.uri+">", "<"+rdf.LdpContainsUri+">") {
		return Node{}, ServerManagedPropertyError
	}

	return node, node.writeRdfToDisk(graph)
}

func (node Node) addDirectContainerChild(child Node) error {
	// TODO: account for isMemberOfRelation
	targetUri := removeAngleBrackets(node.membershipResource)
	targetPath := util.PathFromUri(node.rootUri, targetUri)

	targetNode, err := GetNode(node.settings, targetPath)
	if err != nil {
		log.Printf("Could not find target node %s.", targetPath)
		return err
	}

	tripleForTarget := rdf.NewTriple("<"+targetNode.uri+">", node.hasMemberRelation, "<"+child.uri+">")

	err = targetNode.store.AppendToFile(metaFile, tripleForTarget.StringLn())
	if err != nil {
		log.Printf("Error appending child %s to %s. %s", child.uri, targetNode.uri, err)
		return err
	}
	return nil
}

func (node *Node) loadNode(isIncludeBody bool) error {
	err := node.loadMeta()
	if err != nil {
		return err
	}

	if node.isRdf || isIncludeBody == false {
		return nil
	}

	return node.loadBinary()
}

func (node *Node) loadBinary() error {
	var err error
	node.binary, err = node.store.ReadFile(dataFile)
	return err
}

func (node *Node) loadMeta() error {
	if !node.store.Exists() {
		return NodeNotFoundError
	}

	meta, err := node.store.ReadFile(metaFile)
	if err != nil {
		return err
	}

	node.graph, err = rdf.StringToGraph(meta, node.uri)
	if err != nil {
		return err
	}

	if node.graph.IsRdfSource("<" + node.uri + ">") {
		node.setAsRdf()
	} else {
		node.setAsNonRdf()
	}
	return nil
}

func (node *Node) writeNonRdfToDisk(graph rdf.RdfGraph, reader io.ReadCloser) error {
	node.graph = graph
	node.setETag()
	node.appendTriple(rdfTypePredicate, "<"+rdf.LdpResourceUri+">")
	node.appendTriple(rdfTypePredicate, "<"+rdf.LdpNonRdfSourceUri+">")
	node.setAsNonRdf()
	return node.writeToDisk(reader)
}

func (node *Node) writeRdfToDisk(graph rdf.RdfGraph) error {
	node.graph = graph
	node.setETag()
	node.appendTriple(rdfTypePredicate, "<"+rdf.LdpResourceUri+">")
	node.appendTriple(rdfTypePredicate, "<"+rdf.LdpRdfSourceUri+">")
	node.appendTriple(rdfTypePredicate, "<"+rdf.LdpContainerUri+">")
	node.appendTriple(rdfTypePredicate, "<"+rdf.LdpBasicContainerUri+">")
	node.setAsRdf()
	return node.writeToDisk(nil)
}

func (node *Node) writeToDisk(reader io.ReadCloser) error {
	// Write the RDF metadata
	err := node.store.SaveFile(metaFile, node.graph.String())
	if err != nil {
		return err
	}

	if node.isRdf {
		return nil
	}

	// Write the binary...
	err = node.store.SaveReader(dataFile, reader)
	if err != nil {
		return err
	}

	// ...update the copy in memory (this would get
	// tricky when we switch "node.binary" to a
	// reader.
	node.binary, err = node.store.ReadFile(dataFile)
	return err
}

func (node *Node) setAsRdf() {
	subject := "<" + node.uri + ">"
	node.isRdf = true
	node.headers = make(map[string][]string)
	node.headers["Content-Type"] = []string{rdf.TurtleContentType}

	if node.graph.IsBasicContainer(subject) {
		node.headers["Allow"] = []string{"GET, HEAD, POST, PUT, PATCH"}
	} else {
		node.headers["Allow"] = []string{"GET, HEAD, PUT, PATCH"}
	}
	node.headers["Accept-Post"] = []string{"text/turtle"}
	node.headers["Accept-Patch"] = []string{"text/turtle"}

	node.headers["Etag"] = []string{node.Etag()}

	links := make([]string, 0)
	links = append(links, rdf.LdpResourceLink)
	if node.graph.IsBasicContainer(subject) {
		node.isBasicContainer = true
		links = append(links, rdf.LdpContainerLink)
		links = append(links, rdf.LdpBasicContainerLink)
		// TODO: validate membershipResource is a sub-URI of rootURI
		node.membershipResource, node.hasMemberRelation, node.isDirectContainer = node.graph.GetDirectContainerInfo()
		if node.isDirectContainer {
			links = append(links, rdf.LdpDirectContainerLink)
		}
	}
	node.headers["Link"] = links
}

func (node *Node) setAsNonRdf() {
	// TODO Figure out a way to pass the binary as a stream
	node.isRdf = false
	node.binary = ""
	node.headers = make(map[string][]string)

	describedByLink := fmt.Sprintf("<%s?metadata=yes>; rel=\"describedby\"; anchor=\"%s\"", node.uri, node.uri)
	node.headers["Link"] = []string{describedByLink, rdf.LdpResourceLink, rdf.LdpNonRdfSourceLink}

	node.headers["Allow"] = []string{"GET, HEAD, PUT"}
	node.headers["Content-Type"] = []string{removeQuotes(node.nonRdfContentType())}
	node.headers["Etag"] = []string{node.Etag()}
}

func calculateEtag() string {
	// TODO: Come up with a more precise value.
	now := time.Now().Format(time.RFC3339)
	etag := strings.Replace(now, ":", "_", -1)
	return "\"" + etag + "\""
}

func newNode(settings Settings, path string) Node {
	if strings.HasPrefix(path, "http://") {
		panic("newNode expects a path, received a URI: " + path)
	}
	var node Node
	node.settings = settings
	pathOnDisk := util.PathConcat(settings.dataPath, path)
	node.store = textstore.NewStore(pathOnDisk)
	node.rootUri = settings.RootUri()
	node.uri = util.UriConcat(node.rootUri, path)
	return node
}

func removeAngleBrackets(text string) string {
	if strings.HasPrefix(text, "<") && strings.HasSuffix(text, ">") {
		return text[1 : len(text)-1]
	}
	return text
}

func removeQuotes(text string) string {
	if strings.HasPrefix(text, "\"") && strings.HasSuffix(text, "\"") {
		return text[1 : len(text)-1]
	}
	return text
}
<commit_msg>Tweaks to PATCH<commit_after>package ldp

import (
	"errors"
	"fmt"
	"io"
	"ldpserver/rdf"
	"ldpserver/textstore"
	"ldpserver/util"
	"log"
	"strings"
	"time"
)

var NodeNotFoundError = errors.New("Node not found")
var DuplicateNodeError = errors.New("Node already exists")
var EtagMissingError = errors.New("Missing Etag")
var EtagMismatchError = errors.New("Etag mismatch")
var ServerManagedPropertyError = errors.New("Attempted to update server managed property")

const metaFile = "meta.rdf"
const dataFile = "data.txt"
const etagPredicate = "<" + rdf.ServerETagUri + ">"
const rdfTypePredicate = "<" + rdf.RdfTypeUri + ">"
const contentTypePredicate = "<" + rdf.ServerContentTypeUri + ">"

type Node struct {
	isRdf   bool
	uri     string
	headers map[string][]string
	graph   rdf.RdfGraph
	binary  string // should be []byte or reader

	settings Settings
	rootUri  string // http://localhost/
	store    textstore.Store

	isBasicContainer   bool
	isDirectContainer  bool
	membershipResource string
	hasMemberRelation  string
	// TODO isMemberOfRelation string
}

func (node Node) AddChild(child Node) error {
	triple := rdf.NewTriple("<"+node.uri+">", "<"+rdf.LdpContainsUri+">", "<"+child.uri+">")
	err := node.store.AppendToFile(metaFile, triple.StringLn())
	if err != nil {
		return err
	}

	if node.isDirectContainer {
		return node.addDirectContainerChild(child)
	}
	return nil
}

func (node Node) Content() string {
	if node.isRdf {
		return node.graph.String()
	}
	return node.binary
}

func (node Node) Metadata() string {
	return node.graph.String()
}

func (node Node) nonRdfContentType() string {
	if node.isRdf {
		panic("Cannot call NonRdfContentType() for an RDF node")
	}
	triple, found := node.graph.FindTriple("<"+node.uri+">", contentTypePredicate)
	if !found {
		return "application/binary"
	}
	return triple.Object()
}

func (node Node) DebugString() string {
	if !node.isRdf {
		return fmt.Sprintf("Non-RDF: %s", node.uri)
	}

	triples := ""
	for i, triple := range node.graph {
		triples += fmt.Sprintf("%d %s\n", i, triple)
	}
	debugString := fmt.Sprintf("RDF: %s\n %s", node.uri, triples)
	return debugString
}

func (node *Node) Etag() string {
	subject := "<" + node.uri + ">"
	etag, etagFound := node.graph.GetObject(subject, "<"+rdf.ServerETagUri+">")
	if !etagFound {
		panic(fmt.Sprintf("No etag found for node %s", node.uri))
	}
	return etag
}

func (node Node) HasTriple(predicate, object string) bool {
	return node.graph.HasTriple("<"+node.uri+">", predicate, object)
}

func (node Node) Headers() map[string][]string {
	return node.headers
}

func (node Node) IsBasicContainer() bool {
	return node.isBasicContainer
}

func (node Node) IsDirectContainer() bool {
	return node.isDirectContainer
}

func (node Node) IsRdf() bool {
	return node.isRdf
}

func (node Node) Uri() string {
	return node.uri
}

func (node *Node) Patch(triples string) error {
	if !node.isRdf {
		return errors.New("Cannot PATCH non-RDF Source")
	}

	userGraph, err := rdf.StringToGraph(triples, "<"+node.uri+">")
	if err != nil {
		return err
	}

	if hasServerManagedProperties(userGraph, node.uri) {
		return ServerManagedPropertyError
	}

	// This is pretty useless as-is since it does not allow to update
	// a triple. It always adds triples.
	node.graph.Append(userGraph)
	return node.writeRdfToDisk(node.graph)
}

func (node Node) Path() string {
	return util.PathFromUri(node.rootUri, node.uri)
}

func (node Node) String() string {
	return node.uri
}

func (node *Node) appendTriple(predicate, object string) {
	node.graph.AppendTriple2("<"+node.uri+">", predicate, object)
}

func (node *Node) setETag() {
	node.graph.SetObject("<"+node.uri+">", etagPredicate, calculateEtag())
}

func GetNode(settings Settings, path string) (Node, error) {
	node := newNode(settings, path)
	err := node.loadNode(true)
	return node, err
}

func GetHead(settings Settings, path string) (Node, error) {
	node := newNode(settings, path)
	err := node.loadNode(false)
	return node, err
}

func NewRdfNode(settings Settings, triples string, path string) (Node, error) {
	node := newNode(settings, path)
	graph, err := rdf.StringToGraph(triples, "<"+node.uri+">")
	if err != nil {
		return Node{}, err
	}
	return node, node.writeRdfToDisk(graph)
}

func NewNonRdfNode(settings Settings, reader io.ReadCloser, path, triples string) (Node, error) {
	node := newNode(settings, path)
	graph, err := rdf.StringToGraph(triples, "<"+node.uri+">")
	if err != nil {
		return Node{}, err
	}
	return node, node.writeNonRdfToDisk(graph, reader)
}

func ReplaceNonRdfNode(settings Settings, reader io.ReadCloser, path, etag, triples string) (Node, error) {
	node, err := GetHead(settings, path)
	if err != nil {
		return Node{}, err
	}

	if node.isRdf {
		return Node{}, errors.New("Cannot replace RDF source with a Non-RDF source")
	}

	if etag == "" {
		return Node{}, EtagMissingError
	}

	if node.Etag() != etag {
		// log.Printf("Cannot replace RDF source. Etag mismatch. Expected: %s. Found: %s", node.Etag(), etag)
		return Node{}, EtagMismatchError
	}

	var graph rdf.RdfGraph
	if triples != "" {
		graph, err = rdf.StringToGraph(triples, "<"+node.uri+">")
		if err != nil {
			return Node{}, err
		}
	}

	return node, node.writeNonRdfToDisk(graph, reader)
}

func ReplaceRdfNode(settings Settings, triples string, path string, etag string) (Node, error) {
	node, err := GetNode(settings, path)
	if err != nil {
		return Node{}, err
	}

	if !node.isRdf {
		return Node{}, errors.New("Cannot replace non-RDF source with an RDF source")
	}

	if etag == "" {
		return Node{}, EtagMissingError
	}

	if node.Etag() != etag {
		// log.Printf("Cannot replace RDF source. Etag mismatch. Expected: %s. Found: %s", node.Etag(), etag)
		return Node{}, EtagMismatchError
	}

	graph, err := rdf.StringToGraph(triples, "<"+node.uri+">")
	if err != nil {
		return Node{}, err
	}

	if hasServerManagedProperties(graph, node.uri) {
		return Node{}, ServerManagedPropertyError
	}

	return node, node.writeRdfToDisk(graph)
}

func (node Node) addDirectContainerChild(child Node) error {
	// TODO: account for isMemberOfRelation
	targetUri := removeAngleBrackets(node.membershipResource)
	targetPath := util.PathFromUri(node.rootUri, targetUri)

	targetNode, err := GetNode(node.settings, targetPath)
	if err != nil {
		log.Printf("Could not find target node %s.", targetPath)
		return err
	}

	tripleForTarget := rdf.NewTriple("<"+targetNode.uri+">", node.hasMemberRelation, "<"+child.uri+">")

	err = targetNode.store.AppendToFile(metaFile, tripleForTarget.StringLn())
	if err != nil {
		log.Printf("Error appending child %s to %s. %s", child.uri, targetNode.uri, err)
		return err
	}
	return nil
}

func (node *Node) loadNode(isIncludeBody bool) error {
	err := node.loadMeta()
	if err != nil {
		return err
	}

	if node.isRdf || isIncludeBody == false {
		return nil
	}

	return node.loadBinary()
}

func (node *Node) loadBinary() error {
	var err error
	node.binary, err = node.store.ReadFile(dataFile)
	return err
}

func (node *Node) loadMeta() error {
	if !node.store.Exists() {
		return NodeNotFoundError
	}

	meta, err := node.store.ReadFile(metaFile)
	if err != nil {
		return err
	}

	node.graph, err = rdf.StringToGraph(meta, node.uri)
	if err != nil {
		return err
	}

	if node.graph.IsRdfSource("<" + node.uri + ">") {
		node.setAsRdf()
	} else {
		node.setAsNonRdf()
	}
	return nil
}

func (node *Node) writeNonRdfToDisk(graph rdf.RdfGraph, reader io.ReadCloser) error {
	node.graph = graph
	node.setETag()
	node.appendTriple(rdfTypePredicate, "<"+rdf.LdpResourceUri+">")
	node.appendTriple(rdfTypePredicate, "<"+rdf.LdpNonRdfSourceUri+">")
	node.setAsNonRdf()
	return node.writeToDisk(reader)
}

func (node *Node) writeRdfToDisk(graph rdf.RdfGraph) error {
	node.graph = graph
	node.setETag()
	node.appendTriple(rdfTypePredicate, "<"+rdf.LdpResourceUri+">")
	node.appendTriple(rdfTypePredicate, "<"+rdf.LdpRdfSourceUri+">")
	node.appendTriple(rdfTypePredicate, "<"+rdf.LdpContainerUri+">")
	node.appendTriple(rdfTypePredicate, "<"+rdf.LdpBasicContainerUri+">")
	node.setAsRdf()
	return node.writeToDisk(nil)
}

func (node *Node) writeToDisk(reader io.ReadCloser) error {
	// Write the RDF metadata
	err := node.store.SaveFile(metaFile, node.graph.String())
	if err != nil {
		return err
	}

	if node.isRdf {
		return nil
	}

	// Write the binary...
	err = node.store.SaveReader(dataFile, reader)
	if err != nil {
		return err
	}

	// ...update the copy in memory (this would get
	// tricky when we switch "node.binary" to a
	// reader.
	node.binary, err = node.store.ReadFile(dataFile)
	return err
}

func (node *Node) setAsRdf() {
	subject := "<" + node.uri + ">"
	node.isRdf = true
	node.headers = make(map[string][]string)
	node.headers["Content-Type"] = []string{rdf.TurtleContentType}

	if node.graph.IsBasicContainer(subject) {
		node.headers["Allow"] = []string{"GET, HEAD, POST, PUT, PATCH"}
	} else {
		node.headers["Allow"] = []string{"GET, HEAD, PUT, PATCH"}
	}
	node.headers["Accept-Post"] = []string{"text/turtle"}
	node.headers["Accept-Patch"] = []string{"text/turtle"}

	node.headers["Etag"] = []string{node.Etag()}

	links := make([]string, 0)
	links = append(links, rdf.LdpResourceLink)
	if node.graph.IsBasicContainer(subject) {
		node.isBasicContainer = true
		links = append(links, rdf.LdpContainerLink)
		links = append(links, rdf.LdpBasicContainerLink)
		// TODO: validate membershipResource is a sub-URI of rootURI
		node.membershipResource, node.hasMemberRelation, node.isDirectContainer = node.graph.GetDirectContainerInfo()
		if node.isDirectContainer {
			links = append(links, rdf.LdpDirectContainerLink)
		}
	}
	node.headers["Link"] = links
}

func (node *Node) setAsNonRdf() {
	// TODO Figure out a way to pass the binary as a stream
	node.isRdf = false
	node.binary = ""
	node.headers = make(map[string][]string)

	describedByLink := fmt.Sprintf("<%s?metadata=yes>; rel=\"describedby\"; anchor=\"%s\"", node.uri, node.uri)
	node.headers["Link"] = []string{describedByLink, rdf.LdpResourceLink, rdf.LdpNonRdfSourceLink}

	node.headers["Allow"] = []string{"GET, HEAD, PUT"}
	node.headers["Content-Type"] = []string{removeQuotes(node.nonRdfContentType())}
	node.headers["Etag"] = []string{node.Etag()}
}

func hasServerManagedProperties(graph rdf.RdfGraph, uri string) bool {
	subject := "<" + uri + ">"

	// TODO: What other server-managed properties should we handle?
	properties := []string{rdf.LdpResourceUri, rdf.LdpRdfSourceUri, rdf.LdpNonRdfSourceUri,
		rdf.LdpContainerUri, rdf.LdpBasicContainerUri, rdf.LdpDirectContainerUri, rdf.LdpContainsUri,
		rdf.LdpConstrainedBy}

	for _, property := range properties {
		if graph.HasPredicate(subject, "<"+property+">") {
			return true
		}
	}
	return false
}

func calculateEtag() string {
	// TODO: Come up with a more precise value.
	now := time.Now().Format(time.RFC3339)
	etag := strings.Replace(now, ":", "_", -1)
	return "\"" + etag + "\""
}

func newNode(settings Settings, path string) Node {
	if strings.HasPrefix(path, "http://") {
		panic("newNode expects a path, received a URI: " + path)
	}
	var node Node
	node.settings = settings
	pathOnDisk := util.PathConcat(settings.dataPath, path)
	node.store = textstore.NewStore(pathOnDisk)
	node.rootUri = settings.RootUri()
	node.uri = util.UriConcat(node.rootUri, path)
	return node
}

func removeAngleBrackets(text string) string {
	if strings.HasPrefix(text, "<") && strings.HasSuffix(text, ">") {
		return text[1 : len(text)-1]
	}
	return text
}

func removeQuotes(text string) string {
	if strings.HasPrefix(text, "\"") && strings.HasSuffix(text, "\"") {
		return text[1 : len(text)-1]
	}
	return text
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"fmt"
	"github.com/donatj/mpo"
	"image"
	"image/jpeg"
	"log"
	"os"
)

var (
	format = flag.String("format", "stereo", "Output format [stereo|red-cyan|cyan-red|red-green|green-red]")
	output = flag.String("outfile", "output.jpg", "Output filename")
	help   = flag.Bool("help", false, "Displays this text")
)

func init() {
	flag.Parse()

	if flag.NArg() != 1 {
		fmt.Println("usage: mpo2img <mpofile>")
		flag.PrintDefaults()
		os.Exit(1)
	}
}

func main() {
	m, err := mpo.DecodeAll(flag.Arg(0))
	if err != nil {
		log.Fatalf("err on %v %s", err, flag.Arg(0))
	}

	var img image.Image
	switch *format {
	case "stereo":
		img = m.ConvertToStereo()
	case "red-cyan":
		img, err = m.ConvertToAnaglyph(mpo.RedCyan)
		if err != nil {
			log.Fatal(err)
		}
	case "cyan-red":
		img, err = m.ConvertToAnaglyph(mpo.CyanRed)
		if err != nil {
			log.Fatal(err)
		}
	case "red-green":
		img, err = m.ConvertToAnaglyph(mpo.RedGreen)
		if err != nil {
			log.Fatal(err)
		}
	case "green-red":
		img, err = m.ConvertToAnaglyph(mpo.GreenRed)
		if err != nil {
			log.Fatal(err)
		}
	default:
		log.Fatal("Unknown format:", *format)
	}

	f, err := os.OpenFile(*output, os.O_CREATE|os.O_WRONLY, 0666)
	if err != nil {
		log.Fatal(err)
	}

	if err = jpeg.Encode(f, img, nil); err != nil {
		log.Fatal(err)
	}
}
<commit_msg>Adjusted mpo2img tool fo changes to mpo<commit_after>package main

import (
	"flag"
	"fmt"
	"github.com/donatj/mpo"
	"image"
	"image/jpeg"
	"log"
	"os"
)

var (
	format = flag.String("format", "stereo", "Output format [stereo|red-cyan|cyan-red|red-green|green-red]")
	output = flag.String("outfile", "output.jpg", "Output filename")
	help   = flag.Bool("help", false, "Displays this text")
)

func init() {
	flag.Parse()

	if flag.NArg() != 1 {
		fmt.Println("usage: mpo2img <mpofile>")
		flag.PrintDefaults()
		os.Exit(1)
	}
}

func main() {
	r, err := os.Open(flag.Arg(0))
	if err != nil {
		log.Fatalf("err on %v %s", err, flag.Arg(0))
	}

	m, err := mpo.DecodeAll(r)
	if err != nil {
		log.Fatalf("err on %v %s", err, flag.Arg(0))
	}

	var img image.Image
	switch *format {
	case "stereo":
		img = m.ConvertToStereo()
	case "red-cyan":
		img, err = m.ConvertToAnaglyph(mpo.RedCyan)
		if err != nil {
			log.Fatal(err)
		}
	case "cyan-red":
		img, err = m.ConvertToAnaglyph(mpo.CyanRed)
		if err != nil {
			log.Fatal(err)
		}
	case "red-green":
		img, err = m.ConvertToAnaglyph(mpo.RedGreen)
		if err != nil {
			log.Fatal(err)
		}
	case "green-red":
		img, err = m.ConvertToAnaglyph(mpo.GreenRed)
		if err != nil {
			log.Fatal(err)
		}
	default:
		log.Fatal("Unknown format:", *format)
	}

	f, err := os.OpenFile(*output, os.O_CREATE|os.O_WRONLY, 0666)
	if err != nil {
		log.Fatal(err)
	}

	if err = jpeg.Encode(f, img, nil); err != nil {
		log.Fatal(err)
	}
}
<|endoftext|>


<commit_before>package responses

import (
	"bufio"
	"encoding/json"
	"fmt"
	"github.com/boltdb/bolt"
	"github.com/perthgophers/puddle/messagerouter"
	"io"
	"log"
	"math/rand"
	"strings"
	"time"
)

// BokBok is a smart chat bot
type BokBok struct {
	db        *bolt.DB
	Channel   string
	prefixLen int
}

// NewBokBok makes a BoKBok and opens the bolt database
func NewBokBok(prefixLen int) *BokBok {
	var err error = nil
	bkbk := new(BokBok)
	bkbk.db, err = bolt.Open("./markovchains.db", 0600, &bolt.Options{Timeout: 10 * time.Second})
	if err != nil {
		log.Fatal(err)
	}

	bkbk.db.Update(func(tx *bolt.Tx) error {
		tx.CreateBucketIfNotExists([]byte("all"))
		return nil
	})

	bkbk.prefixLen = prefixLen

	return bkbk
}

// RespondHere allows the user to apply a channel to respond to
// Triggered by !bokbok <channel>
func (bkbk *BokBok) RespondHere(cr *messagerouter.CommandRequest, w messagerouter.ResponseWriter) error {
	bkbk.Channel = cr.Message.Channel

	w.Write("Channel has been set")

	return nil
}

// Processes Message builds or amends the Markov Chain for "all" and the individual user
func (bkbk *BokBok) ProcessMessage(cr *messagerouter.CommandRequest, w messagerouter.ResponseWriter) error {
	bkbk.db.Update(func(tx *bolt.Tx) error {
		tx.CreateBucketIfNotExists([]byte(cr.Username))
		return nil
	})
	ch := bkbk.Chain(cr.Username)
	ch.BuildFromString(cr.Text)

	allch := bkbk.Chain("all")
	allch.BuildFromString(cr.Text)

	bkbk.SaveChains(ch, allch)
	return nil
}

//Respond reponds to message
func (bkbk *BokBok) Respond(cr *messagerouter.CommandRequest, w messagerouter.ResponseWriter) {
	allch := bkbk.Chain("all")
	w.Write(fmt.Sprintf("@%s: %s", cr.Username, allch.Generate()))
}

// MaybeRespond might respond, or it might not, for top kek
func (bkbk *BokBok) MaybeRespond(cr *messagerouter.CommandRequest, w messagerouter.ResponseWriter) error {
	if cr.Message.Channel == cr.Message.User {
		bkbk.Respond(cr, w)
		return nil
	}
	if cr.Message.User != "0" && cr.Message.Channel != bkbk.Channel {
		return nil
	}
	if bkbk.YesNo() {
		bkbk.Respond(cr, w)
	}

	return nil
}

// Prefix is a Markov chain prefix of one or more words.
type Prefix []string

// String returns the Prefix as a string (for use as a map key).
func (p Prefix) String() string {
	return strings.Join(p, " ")
}

// Shift removes the first word from the Prefix and appends the given word.
func (p Prefix) Shift(word string) {
	copy(p, p[1:])
	p[len(p)-1] = word
}

// Chain contains a map ("chain") of prefixes to a list of suffixes.
// A prefix is a string of prefixLen words joined with spaces.
// A suffix is a single word. A prefix can have multiple suffixes.
type Chain struct {
	Username  string
	Chain     map[string][]string
	PrefixLen int
}

// Marshal encodes a chain to json.
func (c *Chain) Marshal() ([]byte, error) {
	enc, err := json.Marshal(c)
	if err != nil {
		return nil, err
	}
	return enc, nil
}

// Decode decodes json to Chain
func (c *Chain) Unmarshal(data []byte) error {
	err := json.Unmarshal(data, &c)
	if err != nil {
		return err
	}
	return nil
}

// NewChain returns a new Chain with prefixes of prefixLen words.
func (bkbk *BokBok) NewChain(username string) *Chain {
	c := new(Chain)
	c.PrefixLen = bkbk.prefixLen
	c.Username = username
	c.Chain = make(map[string][]string)

	return c
}

// Build reads text from the provided Reader and
// parses it into prefixes and suffixes that are stored in Chain.
func (c *Chain) Build(r io.Reader) {
	br := bufio.NewReader(r)
	p := make(Prefix, c.PrefixLen)
	for {
		var s string
		if _, err := fmt.Fscan(br, &s); err != nil {
			break
		}
		key := p.String()
		c.Chain[key] = append(c.Chain[key], s)
		p.Shift(s)
	}
}

// BuildFromString ...
func (c *Chain) BuildFromString(s string) {
	p := make(Prefix, c.PrefixLen)
	for _, v := range strings.Split(s, " ") {
		key := p.String()
		c.Chain[key] = append(c.Chain[key], v)
		p.Shift(v)
	}
}

// Generate returns a string of at most n words generated from Chain.
func (c *Chain) Generate() string {
	p := make(Prefix, c.PrefixLen)
	var words []string
	for {
		choices := c.Chain[p.String()]
		if len(choices) == 0 {
			break
		}
		next := choices[rand.Intn(len(choices))]
		words = append(words, next)
		p.Shift(next)
	}
	return strings.Join(words, " ")
}

// Chain retreives chain from bkbk.db. Creates username bucket if it doesn't exist
func (bkbk *BokBok) Chain(username string) *Chain {
	var ch *Chain = bkbk.NewChain(username)
	var data []byte
	bkbk.db.View(func(tx *bolt.Tx) error {
		tx.CreateBucketIfNotExists([]byte(username))

		b := tx.Bucket([]byte(username))
		log.Println("BUCKET", b)
		data = b.Get([]byte("chain"))
		return nil
	})
	if data != nil {
		ch.Unmarshal(data)
	} else {
		bkbk.NewChain(username)
	}

	return ch
}

func (bkbk *BokBok) YesNo() bool {
	n := rand.Intn(6-1) + 1
	fmt.Println(n)
	return n == 3
}

// SaveChains saves chains to the database
func (bkbk *BokBok) SaveChains(chains ...*Chain) error {
	err := bkbk.db.Update(func(tx *bolt.Tx) error {
		for _, ch := range chains {
			b := tx.Bucket([]byte(ch.Username))
			if b == nil {
				return fmt.Errorf("Can't retrieve bucket for %s", ch.Username)
			}
			j, err := ch.Marshal()
			if err != nil {
				return fmt.Errorf("Can't encode chain: %s", err)
			}
			b.Put([]byte("chain"), j)
		}

		return nil
	})
	return err
}

func init() {
	rand.Seed(time.Now().Unix())
	bkbk := NewBokBok(2)
	Handle("*", bkbk.ProcessMessage)
	Handle("*", bkbk.MaybeRespond)
	Handle("!bokbok", bkbk.RespondHere)
}
<commit_msg>database checks<commit_after>package responses

import (
	"bufio"
	"encoding/json"
	"fmt"
	"github.com/boltdb/bolt"
	"github.com/perthgophers/puddle/messagerouter"
	"io"
	"log"
	"math/rand"
	"os"
	"strings"
	"time"
)

// BokBok is a smart chat bot
type BokBok struct {
	db        *bolt.DB
	Channel   string
	prefixLen int
}

// NewBokBok makes a BoKBok and opens the bolt database
func NewBokBok(prefixLen int) *BokBok {
	var err error = nil
	bkbk := new(BokBok)
	bkbk.db, err = bolt.Open("./markovchains.db", 0600, &bolt.Options{Timeout: 10 * time.Second})
	if err != nil {
		os.Remove("./markovchains.db")
		bkbk.db, err = bolt.Open("./markovchains.db", 0600, &bolt.Options{Timeout: 10 * time.Second})
		if err != nil {
			log.Fatal("Can't open markovchains database, tried deleting and reopening. Fail.")
		}
	}

	bkbk.db.Update(func(tx *bolt.Tx) error {
		tx.CreateBucketIfNotExists([]byte("all"))
		return nil
	})

	bkbk.prefixLen = prefixLen

	return bkbk
}

// RespondHere allows the user to apply a channel to respond to
// Triggered by !bokbok <channel>
func (bkbk *BokBok) RespondHere(cr *messagerouter.CommandRequest, w messagerouter.ResponseWriter) error {
	bkbk.Channel = cr.Message.Channel

	w.Write("Channel has been set")

	return nil
}

// Processes Message builds or amends the Markov Chain for "all" and the individual user
func (bkbk *BokBok) ProcessMessage(cr *messagerouter.CommandRequest, w messagerouter.ResponseWriter) error {
	bkbk.db.Update(func(tx *bolt.Tx) error {
		tx.CreateBucketIfNotExists([]byte(cr.Username))
		return nil
	})
	ch := bkbk.Chain(cr.Username)
	ch.BuildFromString(cr.Text)

	allch := bkbk.Chain("all")
	allch.BuildFromString(cr.Text)

	bkbk.SaveChains(ch, allch)
	return nil
}

//Respond reponds to message
func (bkbk *BokBok) Respond(cr *messagerouter.CommandRequest, w messagerouter.ResponseWriter) {
	allch := bkbk.Chain("all")
	w.Write(fmt.Sprintf("@%s: %s", cr.Username, allch.Generate()))
}

// MaybeRespond might respond, or it might not, for top kek
func (bkbk *BokBok) MaybeRespond(cr *messagerouter.CommandRequest, w messagerouter.ResponseWriter) error {
	if cr.Message.Channel == cr.Message.User {
		bkbk.Respond(cr, w)
		return nil
	}
	if cr.Message.User != "0" && cr.Message.Channel != bkbk.Channel {
		return nil
	}
	if bkbk.YesNo() {
		bkbk.Respond(cr, w)
	}

	return nil
}

// Prefix is a Markov chain prefix of one or more words.
type Prefix []string

// String returns the Prefix as a string (for use as a map key).
func (p Prefix) String() string {
	return strings.Join(p, " ")
}

// Shift removes the first word from the Prefix and appends the given word.
func (p Prefix) Shift(word string) {
	copy(p, p[1:])
	p[len(p)-1] = word
}

// Chain contains a map ("chain") of prefixes to a list of suffixes.
// A prefix is a string of prefixLen words joined with spaces.
// A suffix is a single word. A prefix can have multiple suffixes.
type Chain struct {
	Username  string
	Chain     map[string][]string
	PrefixLen int
}

// Marshal encodes a chain to json.
func (c *Chain) Marshal() ([]byte, error) {
	enc, err := json.Marshal(c)
	if err != nil {
		return nil, err
	}
	return enc, nil
}

// Decode decodes json to Chain
func (c *Chain) Unmarshal(data []byte) error {
	err := json.Unmarshal(data, &c)
	if err != nil {
		return err
	}
	return nil
}

// NewChain returns a new Chain with prefixes of prefixLen words.
func (bkbk *BokBok) NewChain(username string) *Chain {
	c := new(Chain)
	c.PrefixLen = bkbk.prefixLen
	c.Username = username
	c.Chain = make(map[string][]string)

	return c
}

// Build reads text from the provided Reader and
// parses it into prefixes and suffixes that are stored in Chain.
func (c *Chain) Build(r io.Reader) {
	br := bufio.NewReader(r)
	p := make(Prefix, c.PrefixLen)
	for {
		var s string
		if _, err := fmt.Fscan(br, &s); err != nil {
			break
		}
		key := p.String()
		c.Chain[key] = append(c.Chain[key], s)
		p.Shift(s)
	}
}

// BuildFromString ...
func (c *Chain) BuildFromString(s string) {
	p := make(Prefix, c.PrefixLen)
	for _, v := range strings.Split(s, " ") {
		key := p.String()
		c.Chain[key] = append(c.Chain[key], v)
		p.Shift(v)
	}
}

// Generate returns a string of at most n words generated from Chain.
func (c *Chain) Generate() string {
	p := make(Prefix, c.PrefixLen)
	var words []string
	for {
		choices := c.Chain[p.String()]
		if len(choices) == 0 {
			break
		}
		next := choices[rand.Intn(len(choices))]
		words = append(words, next)
		p.Shift(next)
	}
	return strings.Join(words, " ")
}

// Chain retreives chain from bkbk.db. Creates username bucket if it doesn't exist
func (bkbk *BokBok) Chain(username string) *Chain {
	var ch *Chain = bkbk.NewChain(username)
	var data []byte
	bkbk.db.View(func(tx *bolt.Tx) error {
		tx.CreateBucketIfNotExists([]byte(username))

		b := tx.Bucket([]byte(username))
		log.Println("BUCKET", b)
		data = b.Get([]byte("chain"))
		return nil
	})
	if data != nil {
		ch.Unmarshal(data)
	} else {
		bkbk.NewChain(username)
	}

	return ch
}

func (bkbk *BokBok) YesNo() bool {
	n := rand.Intn(6-1) + 1
	fmt.Println(n)
	return n == 3
}

// SaveChains saves chains to the database
func (bkbk *BokBok) SaveChains(chains ...*Chain) error {
	err := bkbk.db.Update(func(tx *bolt.Tx) error {
		for _, ch := range chains {
			b := tx.Bucket([]byte(ch.Username))
			if b == nil {
				return fmt.Errorf("Can't retrieve bucket for %s", ch.Username)
			}
			j, err := ch.Marshal()
			if err != nil {
				return fmt.Errorf("Can't encode chain: %s", err)
			}
			b.Put([]byte("chain"), j)
		}

		return nil
	})
	return err
}

func init() {
	rand.Seed(time.Now().Unix())
	bkbk := NewBokBok(2)
	Handle("*", bkbk.ProcessMessage)
	Handle("*", bkbk.MaybeRespond)
	Handle("!bokbok", bkbk.RespondHere)
}
<|endoftext|>


<commit_before>package rest

type ShopScore struct {
	DeliveryScore float32 `json:"delivery_score,string" bson:"delivery_score"`
	ItemScore     float32 `json:"item_score,string" bson:"item_score"`
	ServiceScore  float32 `json:"service_score,string" bson:"service_score"`
}

type Shop struct {
	//AllCount    int        `json:"all_count" bson:"all_count"`
	Bulletin    string     `json:"bulletin" bson:"bulletin,omitempty"`
	Cid         int        `json:"cid" bson:"cid"`
	//Created     string     `json:"created" bson:"created"`
	Desc        string     `json:"desc" bson:"desc"`
	//Modified    string     `json:"modified" bson:"modified"`
	Nick        string     `json:"nick" bson:"nick"`
	PicPath     string     `json:"pic_path" bson:"pic_path"`
	//RemainCount int        `json:"remain_count" bson:"remain_count"`
	ShopScore   *ShopScore `json:"shop_score" bson:"shop_score"`
	Sid         int        `json:"sid" bson:"sid"`
	Title       string     `json:"title" bson:"title"`
	//UsedCount   int        `json:"used_count" bson:"used_count"`
}

type ShopGetResponse struct {
	Shop *Shop `json:"shop"`
}

type ShopGetResponseResult struct {
	Response *ShopGetResponse `json:"shop_get_response"`
}
<commit_msg>update<commit_after>package rest

import "time"

type ShopScore struct {
	DeliveryScore float32   `json:"delivery_score,string" bson:"delivery_score"`
	ItemScore     float32   `json:"item_score,string" bson:"item_score"`
	ServiceScore  float32   `json:"service_score,string" bson:"service_score"`
	Credit        string    `json:"credit" bson:"credit"`
	PraiseRate    float32   `json:"praise_rate" bson:"praise_rate"`
	UpdatedTime   time.Time `json:"updated_time" bson:"updated_time"`
}

type Shop struct {
	//AllCount    int        `json:"all_count" bson:"all_count"`
	Bulletin    string     `json:"bulletin" bson:"bulletin,omitempty"`
	Cid         int        `json:"cid" bson:"cid"`
	//Created     string     `json:"created" bson:"created"`
	Desc        string     `json:"desc" bson:"desc"`
	//Modified    string     `json:"modified" bson:"modified"`
	Nick        string     `json:"nick" bson:"nick"`
	PicPath     string     `json:"pic_path" bson:"pic_path"`
	//RemainCount int        `json:"remain_count" bson:"remain_count"`
	ShopScore   *ShopScore `json:"shop_score" bson:"shop_score"`
	Sid         int        `json:"sid" bson:"sid"`
	Title       string     `json:"title" bson:"title"`
	//UsedCount   int        `json:"used_count" bson:"used_count"`
	MainProducts string     `json:"main_products" bson:"main_products"`
}

type ShopGetResponse struct {
	Shop *Shop `json:"shop"`
}

type ShopGetResponseResult struct {
	Response *ShopGetResponse `json:"shop_get_response"`
}
<|endoftext|>