Let us go to the modeling basics. Let us also learn and join this nice trilogy. Actually, teaching is very easy. I will be done teaching in another 5 minutes of the modeling basics. Essentially, all system dynamics model consists of exactly three elements. One is the stock or level which accumulates over time. Second is flow or a rate which causes stocks to change over time. So, we have stocks, we have flows and then we have auxiliary variables, information which help define other instantaneous variables or calculations. So, on the visual representation of them, we can look at it like this where the rectangle you see is called as stock.  I mean the direction of arrow represents inflow to the stock and direction of arrow can represent the outflow of the stock. At the end of it, you see kind of cloud kind of thing. This kind of represents an infinite sink and an infinite source, sorry, kind of presence. An example could be something as simple like you know if you are modeling inventory then production rate affects inventory and shipment rate affects inventory. How it affects is intuitive, right? As the production rate is more, inventory is going to increase. As shipment rate is more, then inventory is going to fall down. So, we can represent it simply as these rectangles for stocks and these thick arrows with a valve to represent the rates, close. And these are the only three constructs you need to model, however complex a system you want. Whatever we discussed yesterday, we know we had looked at the examples for the road traffic and road congestion modeling to various other examples we have been studying. We are just going to be modeling it as stocks, close and auxiliary variables. So, if you want to imagine, say for example, hydraulic metaphor, you can imagine a kind of a water tank, I have inflow to the tank, inflow to the tank and then I have an outflow to the tank. So, very simplistic kind of metaphor of course, so you can whenever there is inflows and outflows, we are used to looking at it with say some set of valves within the system. So, this is the same idea that we are using it here and in this way. So, again these are flows, so it is called stock or level, it means the same thing, flow or rate or some books even measure it as flow rate, it depends on what you look. So, it all means the same thing, flow rate or flow rate. The quick load of caution, see here this, though it is a hydraulic metaphor, you know that for example, when inflow is kind of say stops and outflow is always on, then after a point the tank will become empty and then no further water will flow, right. So, if it becomes empty, no further outflow occurs, so that is for the hydraulic metaphor. But if you look at this just the basic model of it, it is nothing but a set of equation. So, in equations especially when you are trying to simulate it, the inflows and outflows can take positive or negative values, there is nothing which restricts it. So, if you take outflows positive then stock will reduce, but outflows negative that means stock is going to increase. So, there is no other check that is done automatically with the computer here, we are back to the real basics of how we are viewing as the equations. For example, we can view it as an integral, view it as integral, you can say stock at time t, this is an integral of time 0 to current time t, inflow of time s minus inflow of time s ds plus initial value of stock, the t is 0 is the let us say initial, so the underlying model is nothing but a you know integral or you can write it as a differential equation or you can write it as d stock by dt, nothing but net change in stock is nothing but your net flow, nothing but your inflow time t minus outflow, so once you make a mapping of your model in terms of stocks and flows, automatically you have defined these differential equations into the system. The system is the stock is going to change by the inflows and outflows precisely in this manner. And once you have set up a differential equation we can simulate it, some of you have done numerical analysis you may know it, others the beauty of it is you do not need to know, you can give it a system and it will simulate it for you, simplest approach could be an Euler method, it will simulate it for you. So we will see a bit of it, so you understand how the underlying model works, but beyond that we do not need to implement the simulator first, we can try to use the simulator to model the systems and the model. So you remember this, so stock can only change through this double headed valve arrows, I mean this directional arrows and it represents your inflows as well as your outflows and stocks are what is going to be differentiable here, so change in stock is defined as inflows minus outflows, so stock can only be changed through flows nothing else. So we have the decide, we have seen this is a negative feedback system where we have water level and we have decide water level, there is no the gap, I decide how fast I want to open the tap and the water is going to flow in and as an decide water level is reached as actual water level reaches a desired water level, I turn down the faucet and then automatically or manually water, so this in stocks, so what is the stock here? Water level is the stock and what is the flow here? There is a word flow in it, there is only one variable water flow, so better guess the same thing and that is the only thing which is influencing water level and it all stocks can only be changed by the flows, so if the water level is the stock then whatever is coming in the end could be the flow. So we simply define as water flow or water flow rate affecting the water level, then there are other variables, so I can simply map it as let us have decide water level which is an information that I have outside the system and I have defined as a variable here, variable here, I identified the gap, see at the same causal links and then the gap is again connected to the affects the flow rate. So now this is also what we call as a stock flow representation of the model, so this is a causal loop representation but just by moving to the stock flow representation the problem becomes much more grounded, actually you know okay, water level is something that I need to measure, so as soon as when it goes both ways, the stock is, stocks are things that we can actually measure, okay, so let us measure that, so that is the stock, how does the stock change based on water that is flowing, what is the information and need to control it, so I need to know about the decide water level, then I need to somehow figure out the gap, so then those comes as what we call as information of auxiliary variable, so just by these three elements we can actually come up with a much richer representation of the same example, we did in causal loop but with a stock flow representation, so many papers you may find that people quickly jump into stock flow representation to represent the same thing without bothering about the underlying equation, how this gap affects the water flow rate we do not know, right now we have time for it, so this is the representation. Now let us quickly understand the role of stocks and then look at some examples.


Okay, so welcome back. Let's find out if monkey patching is a magic trick or a powerful tool. Welcome, Elizaveta. Hi, my name is Elizaveta Shashkova and today I want to tell you about monkey patching in Python. In this talk I'll try to give the answer to the question. Is monkey patching is just a magic trick or is it a really powerful tool? Just a few words about me. I'm a software developer in the JetBrains company. I work in the PyCharm IDE and I develop Debugger in PyCharm, which is also used in PyDev, the Python IDE for Eclipse. Monkey patching is a dynamic modification of a class or a module at a runtime. Here is a simple example which illustrates what monkey patching is. The standard module math has a square root function, which returns the square root of a number. But if the number is negative, this function raises an exception. We want to change the behavior of this function. So what can we do? We save the original square root function to the attribute original of the module math and replace the square root attribute with our new function, save square root function, which doesn't throw exception for negative numbers and returns that not a number constant. Which is defined in math module. So what happened here? We've got the standard module and changed its behavior inside our program. That means that monkey patching allows us to change third party code without changing the source code secretly. It explains where does the term monkey patching comes from. It believes that it has come from the term guerrilla patch. Guerrilla is a member of group of soldiers who don't belong to a regular army and who fight in a war secretly. This term is referred to changing code secretly and possibly incompatibly with other such patches. It's believed that later this term was transformed to guerrilla patch, which sounds similar, and later it was transformed to monkey patch. As you might already notice, all these terms has rather negative meaning. But despite of it, monkey patching exists in a number of other programming languages. For example in Ruby, you can redefine any method in any class, including the standard modules like string or array. In Ruby, it's named re-open the class. In this example, we replace the standard upcase string modeling with the reverse method. As we can see, the monkey patching is Ruby is almost a part of the language philosophy, because there is even a special simple syntax for doing this. So what about Python? I believe that everybody here remembers the Zen of Python and one of the most important statements in it. Explicit is better than implicit. Monkey patching doesn't satisfy this requirement, because instead of raising explicitness, monkey patching makes Python code less readable and more difficult for understanding. And even in Ruby, we can patch everything. In Python, we can patch almost everything, because on Python level, we can't patch built-ins defined in C. There are some solutions for that case too, patching on C level, but we won't discuss them today. So as you can see, monkey patching is a very interesting tool. It gives you a lot of opportunities and also impose the great demand on the person who uses it. Now let's have, like every object in our galaxy, monkey patching has its own light and dark sides. Now let's have a short survey. Please raise your hand if you're on the light side of monkey patching. Well, and now raise your hand if you're on the dark side of monkey patching. Okay, I would like to start from the light side of monkey patching and consider how we can use it in real life. So as I've already mentioned, we can change the third-party code without changing the source code. And for example, if you found a bug inside in some library and you know how to fix it, you can just you can just apply patch to this library and use the correct version of the library inside your program. But remember that nowadays almost every library is open source. So the best decision is to fix this bug and create pull request and share your fix with other users. The next important example of usage of monkey patching is code instrumentation. You can use monkey patching in order to add performance measurements to your code without changing the code of your project. Also, sometimes tests need to invoke some functionality. It depends on global settings or which invokes code, which cannot be easily tested. A lot of test libraries allows you to replace parts of your system under test with mock objects. And the next important example is changing the standard modules. This point looks similar to the first one, but it's not about bug fixing. Sometimes there is need to change the standard libraries for your own purposes and there are some libraries who do it. Later, we'll consider such an example. It's time for examples. The first example will be from the PyCharm internals. As I've already mentioned, I developed debugger inside PyCharm. And it's very important for us to catch all the new processes created in the user's program in order to add debugger's tracing to these new processes. And monkey patching allows us to do it. Here we catch new processes created with the fork function from the module OS. We define a very simple class, process manager, which takes the original fork function and calls it in the method doFork, the patched version of this function. It calls the original fork function and checks the result. If result is zero, that means that we are situated in the child process, we call our debugger's tracing function, start tracing, and after return the process ID, like the original fork function, does it. How can we use our process manager? It's very simple. We import module OS, create the instance of our project manager class and pass the original OS.fork function to it. And after that, they replace attribute fork of the module OS with our method doFork. And after that, every time when we call OS.fork function, we add our debugger tracing to every new process. The next example is about import hooks. Almost every script starts in with the import statement. And every time we're importing some module, we in fact call built-in import function. Let's try to monkey-patch it too. In the previous example, we patched the OS.fork function, but what if we want to patch some module as soon as possible? As soon as possible means right after importing. That's why we need to create import hook. This is import hook manager class, and it's look very similar to the process manager class. It also saves the original import function and calls it inside the patched version of this function. But also it checks the name of the module, and if the name of the module is the string OS, that means we want to patch the object of our module. We again get the original attribute of the module, create the instance of our process manager, and replace the attribute fork of the module. And like standard import function does it, we return the object of the module. How can we use our import hook manager? It's very simple. We import built-ins, the module whereas the import function situated, create the instance of import hook manager, and again replace the attribute import of this module with our new method. And now every time when we type import OS, it will be patched as soon as possible right after importing. And the third example on the right side is related to the G-event library. G-event is a framework for scalable asynchronous input and output operations based on the green light loop, a lightweight coroutine. It implements its own event loop, so even one-threaded programs are not blocked by the IO operations. That's why G-event library is very useful. But there are blocking system calls in the standard library, including, for example, socket, and when you use such modules in your program, you break the main idea of the G-event library, because your I-O operations becomes synchronous back. In this case, you can replace some statements like import socket with a modulus from the G-event library, which are very similar to the standard modulus, but which are compatible with it. So instead of import socket, you should just write from G-event import socket. But if you already have an application which uses such modules, there is no need to modify such import statements in many, many places, because there is a special module inside G-event, gvent.monkey. It clearly replaces functions and classes in the standard modulus, and after that they can be used together with that library. It allows pu-pies and applications and libraries to become synchronous with no modifications. MonkeyPatching has many interesting and useful applications in real life, like changing third-party code, testing, code instrumentation. MonkeyPatching is a very powerful tool, but MonkeyPatching is a very dangerous tool as well. As I've already mentioned in the beginning of my talk, MonkeyPatching violates the philosophy of Python language. Changes made by MonkeyPatching are not explicit. When you patch something, it leads to the unpredictable behavior of your program. Changes are not documented, and they may be very unexpected for people who use your code. Also, even if you documented your MonkeyPatching, sometimes you can meet people who decided to MonkeyPatch something too, and it will be very sad to realize that you decided to MonkeyPatch the same object. The examples on the dark side of the MonkeyPatching are also very important. And this example will be related to the G-event library again. In this example, I want to show you how MonkeyPatching can lead to creation rather complicated and tricky solutions. As I've already mentioned, the G-event can MonkeyPatch some standard modules in order to easily make Python applications asynchronous without a lot of changes of code. In the docs, the creators of the G-event library mentioned that patching should be done as early as possible in the life cycle of the program. But what happens if user runs the program with G-event patching inside PyCharm's debugger? The debugger has its own event loop based on the standard modules. And after G-event MonkeyPatching, user's program is based on the G-event event loop. But two of these event loops should be separated, because the debugger shouldn't affect user's event loop. It shouldn't break the logic of the user's program. So that means the debugger should use the original versions of modules, like threading, asofic, or socket, instead of patching versions. So that means that we have a problem. Somehow, we should save the original versions of some standard modules and continue to use them simultaneously with the patched versions. Let's try to solve this problem. First, let's consider how the importing in Python works. This is a very, very simplified version of the standard import function. First of all, import function is trying to find the name of the module in the sys.modules dictionary. This dictionary contains the objects of all imported modules, and the keys in this dictionary are the names of these modules, just strings. If the import function didn't find the name of the module in this dictionary, it executes the file again, creates the new object of the module, and put it to the sys.modules dictionary and returns it as a result. Let's create some module saved modules. Here, we import socket module. So that means that after that, it is situated in the sys.modules dictionary, and the key socket is inside keys of this dictionary. After that, we pop the object with key socket from this dictionary. What does it mean? This object is not inside the dictionary, but we still have a link to it. And after that, when we import the socket module again, the import function is trying to find it inside sys.modules dictionary. It can't find it, and it creates another object of this module and put it to the sys.modules dictionary. And after that, we have two objects of our socket module, and one of them is situated in sys.modules dictionary, and another of them is in our secret module. So, how can we use it in our program? We can import bus, we can get access to bus of these objects, but after that, when g-event is trying to patch module socket, it is patching the module which is situated in the sys.modules dictionary. And g-event doesn't know anything about another module, but we know about it. So, that means that we can use bus of these modules, the patched versions and the original one, together and simultaneously. So, as you can see, the solution of the problem was not very easy, because we tried to fix the bug after monkey patching, and we had to create some dirty hex with importing. So, monkey patching can lead to some complicated bugs and to complicated fixes of them. Today, we consider it both sides of monkey patching. Monkey patching has many different and interesting implications in real life, like changing third-party code, code instrumentation, testing, working with standard modules. But monkey patching raising the implicitness of the code. It can lead to some unpredictable behavior and surprising bugs in your program. Sometimes it may be incompatible with other such patches. I believe that sometimes you can use monkey patching in your program, but you should use it if and only if there are no other solutions for your problem. If and only if you are absolutely sure that it is necessary in your case. Monkey patching is a fascinating tool, but monkey patching is a very dangerous tool as well. As for me, I am on the light side of monkey patching. We use it inside patcher, because it is a really powerful tool. Be brave, but also be careful. Thank you. Okay, so now I believe that we have some time for some questions. Does anybody of you have some? I don't know if you are allowed to do this, but can you elaborate on some examples of how you use monkey patching in PyCharm? Sorry, could you repeat your question? Can you describe some instances where you use monkey patching in your work at PyCharm? Yes, some of these examples were from the PyCharm internals. So the example where we catch new processes, we use it inside PyCharm debugger, and the import hooks, we use them inside PyCharm too. And these solutions to protect from monkey patching is used inside PyCharm. So I'll look at these examples. Okay, any other questions? Thank you, thank you for your talk. You mentioned at the beginning using monkey patching for testing. I've seen mocking like the mock module in libraries. Do you use those or do you use monkey patching directly? Because my worry is that if you monkey patch in a test, then surely the next test, or maybe I'm misunderstanding, will have that monkey patched object. In some testing libraries, they use monkey patching. Internally in the library, but not in your own tests. Yes, where I mentioned testing in the light side of monkey patching, I mean that how they use monkey patching in testing libraries. There is no need, sometimes of course you can do it, but there is no need to do it on your own because there are a lot of powerful testing libraries, which already does it for you. Any other questions? This may be a dumb question, but can we not solve the problem of monkey patching by not doing monkey patching, by creating new objects or classes that do the same thing with the monkey patch that we want to do? So the question is, can we avoid monkey patching? Yes, by creating new objects, so we will only use those instead of changing the ones that we want to change. So for example in the OS example, you create like monkey patch OS, and you use that instead of the OS, instead of changing OS? Yes, in this example we monkey patched the module OS, which was already imported, and we monkey patched the function inside it. So my question is, can you not create a new OS? Yes, you can create OS, and in this case we should monkey patch it too. Okay. So there are some possibilities to avoid such monkey patching as we did, but this example doesn't protect us from the solution which was shown in the example of the dark side. Yes. Thank you. Do you have any other questions? Okay, if no, then enjoy the coffee break and let's thank again Elisabeth.


Hello guys in this video We are going to see how to create a video call app in Flutter in Order to do so. I will be using one amazing SDK that is Zego cloud For your knowledge, let me tell you that Zego cloud is a global communication service provider Which provides the developer friendly and powerful SDK as well as APIs in order to build Many communication features on your app such as video call video conference chat Livestreaming and so on So they are focusing on developer friendly code. So they also call it no code So you can simply make your apps very quickly and easily So you can take a look over here If you want to add a video call to your website, just the code is less than 10 lines So you can see the code example over here as well Same way if you want to go through the snippet of any of the language, you can just go through over here The links are there simple apps So this SDK basically provide you so many solutions. Let me just go to Pricing and show you the pricing over here So just scroll here. So the pricing are very transparent and you can take a look here They provide the services such as voice call video call Livestreaming in app chat a effects as well Superboard room kit avatars Cloud recording as well and you can explore more as well. So one more thing if you don't want To jump into an implement, you can just go here into UI kits and here Scroll down and you can see you can test a live video call So you can enter your information and test how it works Let's go back to the pricing. So one more thing whenever you sign up over here You will be getting free 10,000 minutes for the same and you can test your app and test different type of apps So they have already mentioned over there Let me first register over here and show you how we can register it and log in into this so you need to fill the information select your country and Currently in India enter your email After filling the email, you need to click on get code this gonna send a verification code on your email and You have to click on the squirrel. Well, let's find it over here and where it is. Here it is next and where it is there it is verify and Just check your inbox and enter the code over So I will be entering the code now. You can have your password Let me keep one so it and You have to agree this And if you want this product updates, you can select this one as well. Let's go for the track So once it is done It will be asking for company name if you want you can fill it Otherwise, you can just you cannot skip it actually. So you just enter Some information. Let's keep it something engineering industry, IT and You have to add your phone number as well Let's add it quickly and just continue And you can see you are getting 10,000 minutes over here That is free in a trial account So just go to dashboard and this is how your dashboard will look like Okay, so now next step is we will be creating a project and Integrating the ceo cloud UI kit with a word letter app So let's create one project over here first Select what kind of app you want to use. So I will be simply going without voice and video call And you can choose any of these Templates, so I just go next and you can specify project name. So what I will say I will just keep this name So you can keep any name and if you scroll down, you can see there are two ways to get started The either you can use UI kit or you can use the SDK Okay, so we will be going with the simple one. Let's go with the UI kit So it will take some time to create the application. Let's wait for the same Okay, so just Either you can click on the start building your app or it would be redirector by default after couple of seconds. So here we will go for flutter and And Just go force Make sure so we are going with one to one call. So just save and start integration Okay, so now here is your detail Your app ID your app sign This information is required. So let's simply go for the console and you can also retrieve that information with you Okay, so once you go to console, you will be able to see your created project. Just go here And here you can get all the information required. So let's jump to VS code and create Project for the same Okay, so let's create a new project over here application and select the folder and You have to specify the name. So the name should vary from this. Don't worry. It is not required to have same name Let's go here and specify this name and we will add letter along with this so Let's create it So meanwhile the app is created. Let's go here and move to this link that is UI kids So this UI kids is basically a lot of kids They have provided in order to make your app quicker and easier. So they provide 20 plus UI kids Which are open source having 50 plus components and Spotted cross platform. So ready to use easy to customize. So all these features are there So let's scroll down here and you can see the source code is also given for different different languages. So let's go here for the flutter and You can see the example is given over here with step by step guide so scroll down and Here what you need to do you need to add this first of all dependency. So I will copy this go to this and in terminal I Will add this command So meanwhile, it is adding the dependencies. So what I will do? Let's create a new folder over here in order to keep pages and Let's create one home page home underscore page dot dot and And here we will be creating the stateless widget. Okay, so let's give it home page Okay, and instead of doing this we will be returning scaffold and let's remove this const and Inside this scaffold You need to add app bar if you want. So I want one app bar. Let's add the app bar And We need to add some title over here. Let's add const text video call app and I'll just make it center title to And this part is done. So after app bar, I need to add three body part So let's add a save area Whose child would be center widget? whose child And just comma Whose child would be Let's say color Or if you need a button only you can simply add a elevated button And just on press we just keep empty for the time being and the second is child. Let's add calls text with a say start call Okay, let's quickly add one comma here and here we will write the code Okay, so let's go back to main and remove this comments find remove And just remove this as well You don't need anything and here you can replace this with home page statcom And here you can also write video call App and one more thing we can write This debug banner we can make it false Save this Okay, so I think dependencies are installed now So what now we need to do let's go back here And they are saying what we need To import this so we'll import this And in order to make the call We need to write this code Okay, so what do we do? We just copy the whole code And create a new page call underscore page dot dot And you can paste this code over here So what else you need to do go back and you can just use this Import over there and if your dependencies added You will not be able to see this error. So let's import this Material as well. Okay, so all well So here we are getting error. Uh, we don't need to do this. Let's remove this line Because it is modified added And now we need to add these information So just you can go to console You can see the app ID is over here. Copy it from here Paste it over there And the second is app sign go back And you have your app sign over here. So click on this eye You can see the app sign and you can copy this Once copied you can hide it as well Go back and this should be enclosed in single code or double code As it is expecting a string Yep Next is user ID So this is basically the user ID of the user So this can be either created logically or whatever way you want. You can create it So for this example, we are just keeping it static. So let's say user one And the username we will say you One Let's say you one Okay, and the next is caller ID. So which is coming from the constructor So whenever we will call this page, we need to pass the call ID So I will let you know what it is. So this portion is done. Let's do rest of the things first Let's go back Go back to the step by step guide Now you need to do what configure your project So you need to change your compile SDK version to 33 So where it is it is android app build dot grid Go here android app build dot grader and just find for compile SDK version So mentioned it What is the version 33 correct and there is a One more thing min SDK version. So min SDK version should be 21 Okay Just save this And in case you want to remove this error as well Here it is. So you can replace this gradle exception with file not exception Save this This part is done. Let's move next Then we need to add permissions. So copy this. You need to add it under source main manifest Go here into source main and android manifest. So here you need to add it before Or just after the application tag Inside the manifest Save this You can close it go back here and what's next so they're mentioned where we can keep this Okay, then we need to do what we need to just create this for Okay, copy this file name Go here. So it should be under android app Go back under android App we have to create a new file with this name And what should be the content? It should have this content copy this Go here Paste it save it Close it Go back Next we need to do what you need to add this line of code So where do you need to write this code?  So here it is after this release paste this and save this Done this Go back And that is all for android if you want to go ahead with iOS you can follow the instructions mentioned over Okay, so that's all for this side Let's go back And Okay, so this is done Just save this And we will go here into main from where we are calling this home page And from home page we need to do what we need to navigate to call page. Let's do what Navi Gator Dot push And you need to pass material page route. Let's use material Page route and you need to pass The builder function. So let me just use this And here you can pass that const call page And whenever you use this you need to pass this call ID Now this call ID is one So this call ID if you take a look over here, it is not available on your console So it can be generated by yourself or it can be generated by analogic So it is just a what it is just a string. Okay, so it is expecting string this caller ID is Used in order to connect two or more persons So now we are doing one to one calling if you take a look over here We are using one to one video call. So Two users whosoever are connecting With each other, they should have the same call ID. Otherwise, they will not be able to connect So let's give it a caller ID user One user two like this you one you two. Okay So for both side this caller ID should be same So whenever you develop any application you have to maintain the logic to maintain the scholar ID So that is all let's try to run this letter run And before running this command make sure your device is connected And let's wait for this And I have connected it with some casting software That is this AirDroid, so I will add the link in the description if you want to use that So let's wait for this to execute Okay, so if you can see we are facing some problem over here This is due to my adb on my machine So I tried installing different softwares in order to cast screen So the different softwares use different adb versions. So that is what the conflict is Let's try to launch this app and check. Yep, it worked. So it worked This error will not be showing on your machine So I just tried with the different casting software that are using different different adb version that is causing conflict over here. So I will check this later on And the app is working fine. So what I need to do I just remove this Data cable and I will use another device in order to do video call. So I'm connecting the second device So let me just Change what I just change it to user two And user Two And just save it Now I will run it again on my second device Let's run it on second device And Wait Let me connect second device With casting as well. So install it Okay, so app has been installed Let's launch this Okay, so now it is working on both sides So I don't need any data cable. Let's remove this I hope you can see the screens So let's start with the previous device Start the call It is asking for permission for recording the video. So let's use while Using the app same for this mic If using the app And you can see my video over here same we will do with the second device While using the app while using the app and let me just keep it here And you can see just picture I just muted on mobile phones. You can see on the bottom Right side. There is a name here. This is u2 and this is u1 that is user one and user two Okay, so this also give you A lot of options like you can turn off your camera if you want Same way you can just Do like this and you can switch your camera And you can end your call you can mute And unmute Now I just unmuted you can listen my voice and this is for loud speaker as well So just Okay, so that is all you can see it is very easy I just end the call and once I end the call you can see both side call has been ended and you are automatically moved to your home page Okay, so that is all for this video now. I will add the link of all these UI kits pricing and this example as well in the description along with this I will be pushing my code to the GitHub and the link I will be adding in the description So that is all for this video. If you have any doubt do comment in the comment section. Otherwise like share and subscribe Thank you