Skip to content

Commit

Permalink
Added Character Sheets.
Browse files Browse the repository at this point in the history
  • Loading branch information
jtmueller committed Apr 11, 2012
1 parent c92573e commit 944cb1f
Show file tree
Hide file tree
Showing 8 changed files with 216 additions and 11 deletions.
33 changes: 33 additions & 0 deletions EveLib.RavenCache/CharacterCache.fs
Expand Up @@ -14,6 +14,7 @@ type internal CharacterCache(baseClient: FSharp.ICharQueries, store: IDocumentSt
query {
for set in session.Query<WalletSet>() do
where (set.Type = WalletType.Personal && set.Id = charId)
take 1
} |> AsyncQuery.head

match wallets with
Expand Down Expand Up @@ -103,18 +104,50 @@ type internal CharacterCache(baseClient: FSharp.ICharQueries, store: IDocumentSt
return upcast bodies
}

let getCharSheet charId = async {
use session = store.OpenAsyncSession()

let! charSheet =
query {
for cs in session.Query<CharacterSheet>() do
where (cs.Id = charId)
take 1
} |> AsyncQuery.head

match charSheet with
| None ->
let! updated = baseClient.GetCharacterSheet(charId)
session.Store updated
do! session.AsyncSaveChanges()
return updated
| Some cs when cs.CachedUntil < DateTimeOffset.UtcNow ->
try
let! updated = baseClient.GetCharacterSheet(charId)
session.Advanced.Evict cs
session.Store updated
do! session.AsyncSaveChanges()
return updated
with _ ->
return cs
| Some cs ->
return cs
}

interface EveLib.FSharp.ICharQueries with
member x.GetAccountBalance(charId) = getAccountBalance charId
member x.GetMailHeaders(charId) = getMailHeaders charId
member x.GetMailBodies(charId, [<ParamArray>] messageIds) =
getMailBodies charId messageIds
member x.GetCharacterSheet(charId) = getCharSheet charId
interface EveLib.Async.ICharQueries with
member x.GetAccountBalance(charId) = getAccountBalance charId |> Async.StartAsTask
member x.GetMailHeaders(charId) = getMailHeaders charId |> Async.StartAsTask
member x.GetMailBodies(charId, [<ParamArray>] messageIds) =
getMailBodies charId messageIds |> Async.StartAsTask
member x.GetCharacterSheet(charId) = getCharSheet charId |> Async.StartAsTask
interface EveLib.Sync.ICharQueries with
member x.GetAccountBalance(charId) = getAccountBalance charId |> Async.RunSynchronously
member x.GetMailHeaders(charId) = getMailHeaders charId |> Async.RunSynchronously
member x.GetMailBodies(charId, [<ParamArray>] messageIds) =
getMailBodies charId messageIds |> Async.RunSynchronously
member x.GetCharacterSheet(charId) = getCharSheet charId |> Async.RunSynchronously
6 changes: 3 additions & 3 deletions EveLib.RavenCache/EveCache.fs
Expand Up @@ -64,7 +64,7 @@ type internal EveCache(baseClient: FSharp.IEveQueries, store: IDocumentStore) =
let! matches =
query {
for ni in session.Query<NamedItem>() do
where (LinqExtensions.In(ni.Name, names))
where (LinqExtensions.In(ni.ItemName, names))
select ni
} |> AsyncQuery.asIList

Expand All @@ -82,13 +82,13 @@ type internal EveCache(baseClient: FSharp.IEveQueries, store: IDocumentStore) =

let missing =
stillGood
|> Seq.map (fun m -> m.Name)
|> Seq.map (fun m -> m.ItemName)
|> Set.ofSeq
|> Set.difference (names |> Set.ofArray)

let toLoad =
outdated
|> Seq.map (fun m -> m.Name)
|> Seq.map (fun m -> m.ItemName)
|> Seq.append missing

if toLoad |> Seq.exists (fun _ -> true) then
Expand Down
20 changes: 19 additions & 1 deletion EveLib.Tests/CharTests.fs
Expand Up @@ -35,9 +35,27 @@ type BaseCharTests(clientFactory: unit -> FSharp.IEveClient) =
let! charInfo = client.GetCharacters()
let subject = charInfo.Characters |> Seq.head
let! mailHeaders = client.Character.GetMailHeaders(subject.Id)
let! mailBodies = client.Character.GetMailBodies(subject.Id, mailHeaders |> Seq.map (fun h -> h.Id) |> Array.ofSeq)
let mailIds = mailHeaders |> Seq.map (fun h -> h.Id) |> Array.ofSeq
let! mailBodies = client.Character.GetMailBodies(subject.Id, mailIds)
Assert.NotEmpty(mailBodies)
} |> Async.StartAsTask

[<Fact>]
let ``Can get all character sheets`` () =
async {
let client = clientFactory()
let! charInfo = client.GetCharacters()

let! charSheets =
charInfo.Characters
|> Seq.map (fun c -> client.Character.GetCharacterSheet(c.Id))
|> Async.Parallel

Assert.NotEmpty(charSheets)
for cs in charSheets do
Assert.NotNull(cs.CharacterName)
Assert.NotEqual<string>("", cs.CharacterName)
} |> Async.StartAsTask

type RavenCharTests() =
inherit BaseCharTests(fun () -> upcast EveLib.RavenCache.RavenEveClient(apiKey))
86 changes: 86 additions & 0 deletions EveLib/CharacterQueries.fs
Expand Up @@ -65,15 +65,101 @@ type internal CharacterQueries(apiValues: (string * string) list) =
|> Seq.cache
}

let getCharSheet charId = async {
let values = ("characterID", string charId) :: apiValues
let toAugment (el:XElement) =
if isNull el then None
else Some { AugmentName = xelv "augmentatorName" el; AugmentValue = xelv "augmentatorValue" el }
let toRole row =
{ RoleId = xval row?roleID; RoleName = xval row?roleName }
let findRowset name (el:XElement) =
el.Elements(xn "rowset")
|> Seq.tryFind (fun x -> x.Attribute(xn "name").Value = name)
|> Option.map (fun x -> RowSet(x))

let! response = getResponse "/char/CharacterSheet.xml.aspx" values
let r = response.Result
let enhancers = r.Element(xn "attributeEnhancers")
let attributes = r.Element(xn "attributes")

return {
Id = xelv "characterID" r
CharacterName = xelv "name" r
DoB = (xelv "DoB" r) + " +0" |> DateTimeOffset.Parse
Race = xelv "race" r
Bloodline = xelv "bloodLine" r
Ancestry = xelv "ancestry" r
Gender = xelv "gender" r
CorpName = xelv "corporationName" r
CorpId = xelv "corporationID" r
AllianceName = xelvo "allianceName" r
AllianceId = xelvo "allianceID" r
CloneName = xelv "cloneName" r
CloneSkillPoints = xelv "cloneSkillPoints" r
Balance = xelv "balance" r
AttributeEnhancers =
{ MemoryBonus = enhancers.Element(xn "memoryBonus") |> toAugment
PerceptionBonus = enhancers.Element(xn "perceptionBonus") |> toAugment
WillpowerBonus = enhancers.Element(xn "willpowerBonus") |> toAugment
IntelligenceBonus = enhancers.Element(xn "intelligenceBonus") |> toAugment
CharismaBonus = enhancers.Element(xn "charismaBonus") |> toAugment }
Attributes =
{ Intelligence = xelv "intelligence" attributes
Memory = xelv "memory" attributes
Charisma = xelv "charisma" attributes
Perception = xelv "perception" attributes
Willpower = xelv "willpower" attributes }
Skills =
match findRowset "skills" r with
| None -> Seq.empty
| Some rs ->
rs.Rows
|> Seq.map (fun s -> { TypeId = xval s?typeID
SkillPoints = xval s?skillpoints
Level = xval s?level
Published = (string s?published = "1") })
|> Seq.cache
Certificates =
match findRowset "certificates" r with
| None -> Seq.empty
| Some rs -> rs.Rows |> Seq.map (fun c -> int c?certificateID)
CorpRoles =
match findRowset "corporationRoles" r with
| None -> Seq.empty
| Some rs -> rs.Rows |> Seq.map toRole
CorpRolesAtHQ =
match findRowset "corporationRolesAtHQ" r with
| None -> Seq.empty
| Some rs -> rs.Rows |> Seq.map toRole
CorpRolesAtBase =
match findRowset "corporationRolesAtBase" r with
| None -> Seq.empty
| Some rs -> rs.Rows |> Seq.map toRole
CorpRolesAtOther =
match findRowset "corporationRoles" r with
| None -> Seq.empty
| Some rs -> rs.Rows |> Seq.map toRole
CorpTitles =
match findRowset "corporationTitles" r with
| None -> Seq.empty
| Some rs -> rs.Rows |> Seq.map (fun t -> { TitleId = xval t?titleID; TitleName = xval t?titleName })
QueryTime = response.QueryTime
CachedUntil = response.CachedUntil
}
}

interface EveLib.FSharp.ICharQueries with
member x.GetAccountBalance(charId) = getAccountBalance charId
member x.GetMailHeaders(charId) = getMailHeaders charId
member x.GetMailBodies(charId, msgIds) = getMailBodies charId msgIds
member x.GetCharacterSheet(charId) = getCharSheet charId
interface EveLib.Async.ICharQueries with
member x.GetAccountBalance(charId) = getAccountBalance charId |> Async.StartAsTask
member x.GetMailHeaders(charId) = getMailHeaders charId |> Async.StartAsTask
member x.GetMailBodies(charId, msgIds) = getMailBodies charId msgIds |> Async.StartAsTask
member x.GetCharacterSheet(charId) = getCharSheet charId |> Async.StartAsTask
interface EveLib.Sync.ICharQueries with
member x.GetAccountBalance(charId) = getAccountBalance charId |> Async.RunSynchronously
member x.GetMailHeaders(charId) = getMailHeaders charId |> Async.RunSynchronously
member x.GetMailBodies(charId, msgIds) = getMailBodies charId msgIds |> Async.RunSynchronously
member x.GetCharacterSheet(charId) = getCharSheet charId |> Async.RunSynchronously
4 changes: 2 additions & 2 deletions EveLib/EveQueries.fs
Expand Up @@ -14,7 +14,7 @@ type internal EveQueries(apiValues: (string * string) list) =
let! response = getResponse "/eve/CharacterName.xml.aspx" values
let rowset = RowSet(response.Result.Element(xn "rowset"))
return rowset.Rows
|> Seq.map (fun r -> { Name = xval r?name; Id = xval r?characterID; CachedUntil = response.CachedUntil })
|> Seq.map (fun r -> { ItemName = xval r?name; Id = xval r?characterID; CachedUntil = response.CachedUntil })
|> Seq.cache
}

Expand All @@ -23,7 +23,7 @@ type internal EveQueries(apiValues: (string * string) list) =
let! response = getResponse "/eve/CharacterID.xml.aspx" values
let rowset = RowSet(response.Result.Element(xn "rowset"))
return rowset.Rows
|> Seq.map (fun r -> { Name = xval r?name; Id = xval r?characterID; CachedUntil = response.CachedUntil })
|> Seq.map (fun r -> { ItemName = xval r?name; Id = xval r?characterID; CachedUntil = response.CachedUntil })
|> Seq.cache
}

Expand Down
10 changes: 10 additions & 0 deletions EveLib/Extensions.fs
Expand Up @@ -20,6 +20,16 @@ module Extensions =
elif String.IsNullOrEmpty(x.Value) then None
else Some(xval x)

let inline xelv name (parent:XElement) =
let el = parent.Element(xn name)
if isNull el then failwithf "Element not found: %s" name
else xval el

let inline xelvo name (parent:XElement) =
let el = parent.Element(xn name)
if isNull el then None
else Some(xval el)

let (|Element|_|) name (node:XElement) =
if isNull node then
None
Expand Down
3 changes: 3 additions & 0 deletions EveLib/Interfaces.fs
Expand Up @@ -9,6 +9,7 @@ type ICharQueries =
abstract member GetAccountBalance : charId:int -> Async<WalletSet>
abstract member GetMailHeaders : charId:int -> Async<seq<MailHeader>>
abstract member GetMailBodies : charId:int * [<ParamArray>] messageIds:int[] -> Async<seq<MailBody>>
abstract member GetCharacterSheet : charId:int -> Async<CharacterSheet>

type ICorpQueries =
abstract member GetAccountBalance : corpId:int -> Async<WalletSet>
Expand Down Expand Up @@ -37,6 +38,7 @@ type ICharQueries =
abstract member GetAccountBalance : charId:int -> Task<WalletSet>
abstract member GetMailHeaders : charId:int -> Task<seq<MailHeader>>
abstract member GetMailBodies : charId:int * [<ParamArray>] messageIds:int[] -> Task<seq<MailBody>>
abstract member GetCharacterSheet : charId:int -> Task<CharacterSheet>

type ICorpQueries =
abstract member GetAccountBalance : corpId:int -> Task<WalletSet>
Expand Down Expand Up @@ -64,6 +66,7 @@ type ICharQueries =
abstract member GetAccountBalance : charId:int -> WalletSet
abstract member GetMailHeaders : charId:int -> seq<MailHeader>
abstract member GetMailBodies : charId:int * [<ParamArray>] messageIds:int[] -> seq<MailBody>
abstract member GetCharacterSheet : charId:int -> CharacterSheet

type ICorpQueries =
abstract member GetAccountBalance : corpId:int -> WalletSet
Expand Down
65 changes: 60 additions & 5 deletions EveLib/Models.fs
Expand Up @@ -26,7 +26,7 @@ type Character =
member x.PortraitUrl =
sprintf "http://image.eveonline.com/Character/%i_128.jpg" x.Id

type CharacterList = {
and CharacterList = {
mutable Id : int
Characters : seq<Character>
QueryTime : DateTimeOffset
Expand All @@ -35,7 +35,7 @@ type CharacterList = {

type NamedItem = {
mutable Id : int
Name : string
ItemName : string
CachedUntil : DateTimeOffset
}

Expand Down Expand Up @@ -87,7 +87,62 @@ type MailBody = {
CachedUntil : DateTimeOffset
}

type MailBodyList = {
MailBodies : seq<MailBody>
MissingMessageIds : seq<int>
type CharacterSheet = {
mutable Id : int
CharacterName : string
DoB : DateTimeOffset
Race : string
Bloodline : string
Ancestry : string
Gender : string
CorpName : string
CorpId : int
AllianceName : string option
AllianceId : int option
CloneName : string
CloneSkillPoints : int
Balance : decimal
AttributeEnhancers : AttributeEnhancers
Attributes : Attributes
Skills : seq<Skill>
Certificates : seq<int>
CorpRoles : seq<Role>
CorpRolesAtHQ : seq<Role>
CorpRolesAtBase : seq<Role>
CorpRolesAtOther : seq<Role>
CorpTitles : seq<Title>
QueryTime : DateTimeOffset
CachedUntil : DateTimeOffset
}
and Augmentor = {
AugmentName : string
AugmentValue : int
}
and AttributeEnhancers = {
MemoryBonus : Augmentor option
PerceptionBonus : Augmentor option
WillpowerBonus : Augmentor option
IntelligenceBonus : Augmentor option
CharismaBonus : Augmentor option
}
and Attributes = {
Intelligence : int
Memory : int
Charisma : int
Perception : int
Willpower : int
}
and Skill = {
TypeId : int
SkillPoints : int
Level : int
Published : bool
}
and Role = {
RoleId : int64
RoleName : string
}
and Title = {
TitleId : int
TitleName : string
}

0 comments on commit 944cb1f

Please sign in to comment.