I am working with AIMLbot.dll in c#. I saw two functions saveToBinaryFile and loadFromBinaryFile. I think these functions are to store current contents in bot's brain to a file. But it doesn't seems to be working! Means, If I say to remember my name and save the content to GraphMaster.dat file. Next time I load the content of the same file and when I ask my name its giving the wrong answer. My class is as follows.
class AIBot
{
private Bot myBot;
private User myUser;
public AIBot()
{
myBot = new Bot();
myUser = new User("UnknownUser", myBot);
}
public void Initialize()
{
myBot.loadSettings();
myBot.isAcceptingUserInput = false;
myBot.loadAIMLFromFiles();
myBot.isAcceptingUserInput = true;
}
public void Load()
{
if (File.Exists(AppDomain.CurrentDomain.BaseDirectory + #"\Graphmaster.dat"))
myBot.loadFromBinaryFile(AppDomain.CurrentDomain.BaseDirectory + #"\Graphmaster.dat");
}
public string GetResponse(string input)
{
Request r = new Request(input, myUser, myBot);
Result res = myBot.Chat(r);
return (res.Output);
}
public void Save()
{
myBot.saveToBinaryFile(AppDomain.CurrentDomain.BaseDirectory + #"\Graphmaster.dat");
}
}
Can anybody help to point out the problem?
I got a solution for the problem. Hope it will help others.
Save user session like
this.myUser.Predicates.DictionaryAsXML.Save(saveFileDialogDump.FileName);
Load the stored session next time.
this.myUser.Predicates.loadSettings(openFileDialogDump.FileName);
Related
I’m still a beginner in C# and unit testing and I have a problem that I don’t know how to solve.
I've a Mongo Database and I just want to mock this database.
I’ll start by showing you my code before I explain my problem.
Here is my unit test class:
private FollowManager _followManager;
private FollowsDao _followSubstitute;
private UsersDao _userSubstitute;
private IMongoDatabase _database;
private IMongoCollection<Follow> _followMongoCollection;
private IMongoCollection<User> _userMongoCollection;
[OneTimeSetUp]
public void OneTimeSetup()
{
_database = Substitute.For<IMongoDatabase>();
_followMongoCollection = Substitute.For<IMongoCollection<Follow>>();
_userMongoCollection = Substitute.For<IMongoCollection<User>>();
_followSubstitute = new FollowsDao(_database, _followMongoCollection);
_userSubstitute = new UsersDao(_database, _userMongoCollection);
_followManager = new FollowManager(_followSubstitute, _userSubstitute);
}
[TestCase(1, 2)]
[TestCase(3, 4)]
public void AssertThatBuildFollowReturnsValidFollow(int followerId, int followedId)
{
UserFollow userFollow = new UserFollow {Follower = followerId, Followed = followedId};
Follow follow = _followManager.BuildFollow(userFollow);
Assert.IsNotNull(follow);
}
Here is my function that I want to test in my FollowManager:
public Follow BuildFollow(UserFollow follow)
{
User follower = _userDao.FindUserByNumber(follow.Follower).Result;
User followed = _userDao.FindUserByNumber(follow.Followed).Result;
Follow newFollow = new Follow { Follower = follower, Followed = followed, Date = DateTime.Now };
InsertOrUpdateFollow(newFollow);
return newFollow;
}
The FindUserByNumber method will search in the database for a user that matches the id passed as a parameter:
public async Task<User> FindUserByNumber(int number)
{
List<User> result = await _collection.Find(user => user.Number == number && user.Active).ToListAsync();
return result.FirstOrDefault();
}
My problem is:
When I call Follow follow = _followManager.BuildFollow(userFollow); in my unit test, this line InsertOrUpdateFollow(newFollow); in my manager throw an error. It's normal because properties Follower and Followed are null because my database is mocked.
I have a JSON file that contains the list of users of the database and I want to be able to recover my users from this file and not from the database.
With this, I've my users in my JSON file:
List<User> users = JsonConvert.DeserializeObject<List<User>>(File.ReadAllText(#"C:\users-list-api-result.json"));
So, my question is:
How can I test this function with JSON mocked file ?
Thanks in advance!
I am trying to have a button that on button1_click it opens an URL to fetch live exchange rates. i am a little unsure where to actually place the algorithm. so for this purpose can we assume its a blank windows form with a single button that upon clicking prints the fetched data next to the clicked button.This is what i have keep in mind im new to c# and visual studio changed a few things that made my initial code much more confusing to me any simplification helps.
public partial class eth: Form
{
private const string InputUri = #"https://api.bitfinex.com/v1/ticker/ethusd";
public eth()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
public static List<KeyValuePair<string, decimal>> GetCurrencyListFromWeb(out DateTime currencyDate)
{
List<KeyValuePair<string, decimal>> returnList = new List<KeyValuePair<string, decimal>>();
string date = string.Empty;
currencyDate = NewMethod(returnList, ref date);
returnList.Add(new KeyValuePair<string, decimal>("usd", 1));
return returnList;
}
}
private static DateTime NewMethod(List<KeyValuePair<string, decimal>> returnList, ref string date)
{
DateTime currencyDate;
using (XmlReader xmlr = XmlReader.Create(InputUri))
{
xmlr.ReadToFollowing("bid");
while (xmlr.Read())
{
if (xmlr.NodeType != XmlNodeType.Element) continue;
if (xmlr.GetAttribute("timestamp") != null)
{
date = xmlr.GetAttribute("timestamp");
}
else returnList.Add(new KeyValuePair<string, decimal>(xmlr.GetAttribute("ask"), decimal.Parse(xmlr.GetAttribute("last_price"), CultureInfo.InvariantCulture)));
}
currencyDate = DateTime.Parse(date);
}
return currencyDate;
}
}
}
The below code is tested and working fine. You are calling a REST endpoint and it is returning a list of values as a json. I am using the HttpClient to call the endpoint and will need to add the other properties as needed from the documentation. One thing to be mindful is that the results change with the symbols provided. So, will need to provide that responsibility to another class. In fact, you should always move the external library calling to another class to comply with the SRP.
public partial class ExchangeRates : Form
{
public ExchangeRates()
{
InitializeComponent();
}
private const string InputUri = #"https://api.bitfinex.com/v1/ticker/ethusd";
private async void button1_Click(object sender, EventArgs e)
{
var result = await GetTicker();
richTextBox1.AppendText($"mid: {result.Mid}\n");
richTextBox1.AppendText($"bid: {result.Bid}\n");
richTextBox1.AppendText($"ask: {result.Ask}");
}
private static async Task<Ticker> GetTicker()
{
var httpClient = new HttpClient();
var response = await httpClient.GetAsync(InputUri);
if (response.IsSuccessStatusCode)
{
var content = await response.Content.ReadAsStringAsync();
var output = JsonConvert.DeserializeObject<Ticker>(content);
return output;
}
throw new Exception("Ticker exception.");
}
}
public class Ticker
{
[DataMember(Name = "mid")]
public decimal Mid { get; set; }
[DataMember(Name = "bid")]
public decimal Bid { get; set; }
[DataMember(Name = "ask")]
public decimal Ask { get; set; }
// other properties
}
Update 1
Sorry about the issue. I have used Newtonsoft.Json package here. We can use string manipulation also but it is a bit ugly. So, use the JArray from the package to convert the result to an array.
Update 2
Ok, I scrapped the JArray part and went back to string splits.
Update 3
Really sorry, I have used a different end point earlier. I have updated answer according to the required end point. Here you will have to use the JsonConvert class from the same Newtonsoft.Json package. I have also added DataMember attributes for easy deserialization. DataMember is part of System.Runtime.Serialization namespace.
Update 4
Appended the results to a rich text box as you have requested. But, why do want them in a rich text box? These are read only data that you want to display to the users. I believe you should have different labels for each field and display them separately.
First of all - I know this question has been asked. I hardly know C# still learning, a lot of this code is from a tutorial, so I was hoping if I could have a more of direct answer to my actual code. Im making a twitch bot.
private void ViewListUpdate()
{
ViewerBox.Items.Clear();
Chatters AllChatters = ChatClient.GetChatters("name");
chatBox.Text += "Checking the viewer list...";
foreach (string admin in AllChatters.Admins)
{
ViewerBox.Items.Add(admin + Environment.NewLine);
}
foreach (string staff in AllChatters.Staff)
{
ViewerBox.Items.Add(staff + Environment.NewLine);
}
foreach (string globalmod in AllChatters.GlobalMods)
{
ViewerBox.Items.Add(globalmod + Environment.NewLine);
}
foreach (string moderator in AllChatters.Moderators)
{
ViewerBox.Items.Add(moderator + Environment.NewLine);
}
foreach (string viewers in AllChatters.Viewers)
{
ViewerBox.Items.Add(viewers + Environment.NewLine);
}
}
The line that is getting the error (System.IndexOutOfRangeException: 'Index was outside the bounds of the array.') is the following:
Chatters AllChatters = ChatClient.GetChatters("name");
Any help would be great, thanks.
Compiled DLL
I have generated a compiled DLL for you here which you can download and add to your project. You can find this here: https://dropfile.to/9hzvwVX (updated)
Now you can fetch users for a channel like so:
var dataClient = new TwitchTmiClient();
var chatters = dataClient.GetChannelViewers("someTwitchChannelName");
Chatters will now contain a list of users in the active channel, separated by ranks (admin, mod, viewer etc.)
Explanation
Because this question is relevant to my personal interests I decided to add the feature you're looking for to the library I posted in the comments: https://github.com/michidk/TwitchCSharp
Of course, downloading files is always kind of sketchy. So what I did was add a new Twitch client implementation, because chatter data is not stored on the Twitch Kraken API but on the old, https://tmi.twitch.tv API.
namespace TwitchCSharp.Clients
{
public class TwitchTmiClient : ITwitchClient
{
public readonly RestClient restClient;
public TwitchTmiClient(string url = TwitchHelper.TwitchTmiUrl)
{
restClient = new RestClient(url);
restClient.AddHandler("application/json", new DynamicJsonDeserializer());
restClient.AddHandler("text/html", new DynamicJsonDeserializer());
restClient.AddDefaultHeader("Accept", TwitchHelper.twitchAcceptHeader);
}
public ViewerList GetChannelViewers(string channel)
{
var request = new RestRequest("group/user/{channel}/chatters");
request.AddUrlSegment("channel", channel.ToLower());
return restClient.Execute<ViewerList>(request).Data;
}
public RestRequest GetRequest(string url, Method method)
{
return new RestRequest(url, method);
}
}
}
This new Twitch client uses two models to deserialize json into:
namespace TwitchCSharp.Models
{
public class ViewerList
{
[JsonProperty("_links")]
public Dictionary<string, string> Links;
[JsonProperty("chatter_count")]
public int ChatterCount;
[JsonProperty("chatters")]
public Chatter Chatters;
}
}
...
namespace TwitchCSharp.Models
{
public class Chatter
{
[JsonProperty("moderators")] public string[] Moderators;
[JsonProperty("staff")] public string[] Staff;
[JsonProperty("admins")] public string[] Admins;
[JsonProperty("global_mods")] public string[] GlobalMods;
[JsonProperty("viewers")] public string[] Viewers;
}
}
A repository where you can see all the changes can be found here: https://github.com/nbokmans/TwitchCSharp/commit/ec38eecf1d0fbcb0b75c5de597a44582a61deb3d
You can git clone above repository and open it in Visual Studio to build it yourself, if you want to.
public void SerializeObject(string filename, T data)
{
// Get the path of the save game
string fullpath = filename;
// Open the file, creating it if necessary
//if (container.FileExists(filename))
// container.DeleteFile(filename);
FileStream stream = (FileStream)File.Open(fullpath, FileMode.OpenOrCreate);
try
{
// Convert the object to XML data and put it in the stream
XmlSerializer serializer = new XmlSerializer(typeof(T));
serializer.Serialize(stream, data); //Thrown HERE
}
finally
{
// Close the file
stream.Close();
}
}
how do I make the above code stop throwing an InvalidOperationException?
The full error message is:
Unable to generate a temporary class (result=1).
error CS0016: Could not write to output file 'c:\Users[MYUSERNAME]\AppData\Local\Temp\czdgjjs0.dll' -- 'Access is denied.
I have no idea how to get around this error.
I am attempting to serialize my Level class which looks like this:
[Serializable]
public class Level : ISerializable
{
public string Name { get; set; }
public int BestTime { get; set; } //In seconds
public List<Block> levelBlocks { get; set; }
public int Width { get; set; }
public int Height { get; set; }
public Level()
{
}
public Level(SerializationInfo info, StreamingContext ctxt)
{
this.Name = (String)info.GetValue("Name", typeof(String));
this.BestTime = (int)info.GetValue("BestTime", typeof(int));
this.levelBlocks = (List<Block>)info.GetValue("Blocks", typeof(List<Block>));
this.Width = (int)info.GetValue("Width", typeof(int));
this.Height = (int)info.GetValue("Height", typeof(int));
}
public void GetObjectData(SerializationInfo info, StreamingContext ctxt)
{
info.AddValue("Name", this.Name);
info.AddValue("BestTime", this.BestTime);
info.AddValue("Blocks", this.levelBlocks);
info.AddValue("Width", this.Width);
info.AddValue("Height", this.Height);
}
}
My blocks class is implemented in a similar way and holds only a Position Vector that is saved.
Below, my save method:
public static void Save()
{
string filename = "saved.xml";
Level toSave = new Level();
toSave.levelBlocks = new List<Block>();
//TODO: build toSave
toSave.Name = "This is a level!";
toSave.BestTime = 0;
foreach (Entity e in EntityController.Entities)
{
if (e is Block)
{
toSave.levelBlocks.Add((Block)e);
if (e.Position.X > toSave.Width)
toSave.Width = (int)e.Position.X;
if (e.Position.Y > toSave.Height)
toSave.Height = (int)e.Position.Y;
}
}
serializer.SerializeObject(filename, toSave);
}
My program is an XNA game.
Use COMODO antivirus and get CS0016 error?
Open COMODO Command Window (Main Window), and check the SANDBOX. If your application is listed as an application that has been flagged 'limited', simply right click and select the option from the popup to add your application as a Trusted Application. Or just uninstall COMODO and reboot.That should resolve the problem with CS0016 error.
The accepted answer here System.InvalidOperationException: Unable to generate a temporary class (result=1) is likely to have a reasonable solution for you.
One possibility they didn't suggest: if you're using ASP.NET is changing the temp directory in the web.config. Check the tempDirectory attribute of the compilation element (info here http://msdn.microsoft.com/en-us/library/s10awwz0.aspx ) and change to somewhere that your ASP.NET process does have access to.
Ultimately, though, your problem is that the process doing the serialization needs to generate and write some code to disk and doesn't have permissions. You can give that process permissions, change the location to somewhere it does have permissions, or use sgen.exe, depending on what works best for your situation.
I'm trying to use Protobuf-net to save and load data to disk but got stuck.
I have a portfolio of assets that I need to process, and I want to be able to do that as fast as possible. I can already read from a CSV but it would be faster to use a binary file, so I'm looking into Protobuf-Net.
I can't fit all assets into memory so I want to stream them, not load them all into memory.
So what I need to do is expose a large set of records as an IEnumerable. Is this possible with Protobuf-Net? I've tried a couple of things but haven't been able to get it running.
Serializing seems to work, but I haven't been able to read them back in again, I get 0 assets back. Could someone point me in the right direction please? Looked at the methods in the Serializer class but can't find any that covers this case. I this use-case supported by Protobuf-net? I'm using V2 by the way.
Thanks in advance,
Gert-Jan
Here's some sample code I tried:
public partial class MainWindow : Window {
// Generate x Assets
IEnumerable<Asset> GenerateAssets(int Count) {
var rnd = new Random();
for (int i = 1; i < Count; i++) {
yield return new Asset {
ID = i,
EAD = i * 12345,
LGD = (float)rnd.NextDouble(),
PD = (float)rnd.NextDouble()
};
}
}
// write assets to file
private void Write(string path, IEnumerable<Asset> assets){
using (var file = File.Create(path)) {
Serializer.Serialize<IEnumerable<Asset>>(file, assets);
}
}
// read assets from file
IEnumerable<Asset> Read(string path) {
using (var file = File.OpenRead(path)) {
return Serializer.DeserializeItems<Asset>(file, PrefixStyle.None, -1);
}
}
// try it
private void Test() {
Write("Data.bin", GenerateAssets(100)); // this creates a file with binary gibberish that I assume are the assets
var x = Read("Data.bin");
MessageBox.Show(x.Count().ToString()); // returns 0 instead of 100
}
public MainWindow() {
InitializeComponent();
}
private void button2_Click(object sender, RoutedEventArgs e) {
Test();
}
}
[ProtoContract]
class Asset {
[ProtoMember(1)]
public int ID { get; set; }
[ProtoMember(2)]
public double EAD { get; set; }
[ProtoMember(3)]
public float LGD { get; set; }
[ProtoMember(4)]
public float PD { get; set; }
}
figured it out. To deserialize use PrefixBase.Base128 wich apparently is the default.
Now it works like a charm!
GJ
using (var file = File.Create("Data.bin")) {
Serializer.Serialize<IEnumerable<Asset>>(file, Generate(10));
}
using (var file = File.OpenRead("Data.bin")) {
var ps = Serializer.DeserializeItems<Asset>(file, PrefixStyle.Base128, 1);
int i = ps.Count(); // got them all back :-)
}